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 33KB

il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
il y a 3 ans
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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>How to Build Good Software (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.csc.gov.sg/articles/how-to-build-good-software">
  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>How to Build Good Software</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.csc.gov.sg/articles/how-to-build-good-software" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <h2>Why Bad Software Happens to Good People</h2>
  71. <p>Bad software is one of the few things in the world you cannot solve with money. Billion dollar airlines have flight search apps that are often inferior to those built by groups of students. Established taxi
  72. companies the world over have terrible booking apps despite the threat they face from ride-sharing services. And painful corporate IT systems are usually projects with massive budgets, built over the course of many years. Whatever the cause of bad software is, it does not seem to be a lack of funding.</p>
  73. <p>Surprisingly, the root cause of bad software has less to do with specific engineering choices, and more to do with how development projects are managed. The worst software projects often proceed in a very particular way:</p>
  74. <p>The project owners start out wanting to build a specific solution and never
  75. explicitly identify the problem they are trying to solve. They then gather a long list of requirements from a large group of stakeholders. This list is then handed off to a correspondingly large external development team, who get to work building this highly customised piece of software from scratch. Once all the requirements are met, everyone celebrates as the system is launched and the project is declared complete.</p>
  76. <hr>
  77. <h5><em>
  78. The root cause of bad software has less to do with specific engineering choices, and more to do with how development projects are managed.
  79. </em></h5>
  80. <hr>
  81. <p> However, though the system technically meets specifications, severe issues are
  82. found when it is put in the hands of actual users. It is slow, confusing, and
  83. filled with subtle bugs that make using it an exercise in frustration. Unfortunately,
  84. by this time the external development team has been dismissed and there
  85. are no resources left over to make the necessary fixes. By the time a new project
  86. can be initiated years later, all knowledge of what caused these problems has left
  87. the organisation and the cycle starts over again.</p>
  88. <p></p>
  89. <p class="small-text">A Conversation with Li Hongyi (Part 1)<br>
  90. <em>Scroll down for more videos</em></p>
  91. <p>The right coding language, system architecture, or interface design will
  92. vary wildly from project to project. But there are characteristics particular
  93. to software that consistently cause traditional management practices to fail, while allowing small startups to succeed with a shoestring budget:</p>
  94. <p>• Reusing good software is easy;
  95. it is what allows you to build good
  96. things quickly;<br>
  97. • Software is limited not by the amount
  98. of resources put into building it, but
  99. by how complex it can get before it
  100. breaks down; and<br>
  101. • The main value in software is not the
  102. code produced, but the knowledge
  103. accumulated by the people who
  104. produced it.</p>
  105. <p>
  106. </p>
  107. <p>Understanding these characteristics may not guarantee good outcomes, but it
  108. does help clarify why so many projects produce bad outcomes. Furthermore,
  109. these lead to some core operating principles that can dramatically improve
  110. the chances of success:</p>
  111. <p>
  112. </p>
  113. <p>1. Start as simple as possible;<br>
  114. 2. Seek out problems and iterate; and<br>
  115. 3. Hire the best engineers you can.</p>
  116. <p>While there are many subtler factors to consider, these principles form a foundation that lets you get started building good software.</p>
  117. <h2>Reusing Software Lets You Build Good Things Quickly</h2>
  118. <p>Software is easy to copy. At a mechanical level, lines of code can literally be copied and pasted onto another computer. More generally, the internet is full of tutorials on how to build different kinds of systems using ready-made code modules that are available online. Modern software is almost never developed from scratch. Even the most innovative applications are built using existing software that has been combined and modified to achieve a new result.</p>
  119. <p>The biggest source of reusable code modules is the open source community. Open source software is software in which code is freely published for anyone to see and use. Many of the largest contributors to the open source community are giant tech companies. If you want to use a state-of-the-art planet scalable database as Facebook does, just download the code for Cassandra that they open sourced in 2008. If you want to try out Google’s cutting-edge machine learning for yourself, download the TensorFlow system published in 2015. Using open source code does not just make your application development faster, it gives you access to technology that is far more sophisticated than anything
  120. you could have developed yourself. For the most popular open source code, it is even more secure as there are many more people paying attention and fixing vulnerabilities. This is the reason digital technology has made such rapid progress: even the newest engineers can build upon the most advanced tools our profession has to offer.</p>
  121. <p>The advent of cloud services has taken reusability even further, offering the full use of even proprietary systems for just a subscription fee. Need a simple website? Just configure one in a few clicks using a website building service like Squarespace or Wix. A database? Subscribe to a virtual one from Amazon Web Services or Microsoft Azure. Cloud services allow developers to benefit from specialisation; the service provider handles the setup, maintenance, and continued development of a reliable, high-quality piece of software that is used by all its subscribers. This allows software developers to stop wasting time on solved problems and instead focus on delivering actual value.</p>
  122. <p>You cannot make technological progress if all your time is spent on rebuilding existing technology. Software engineering is about building automated systems, and one of the first things that gets automated away is routine software engineering work. The point is to understand what the right systems to reuse are, how to customise them to fit your unique requirements, and fixing novel problems
  123. discovered along the way.</p>
  124. <hr>
  125. <h5><em>
  126. Software engineering is about building automated systems, and one of the first things that gets automated away is routine software engineering work.
  127. </em></h5>
  128. <hr>
  129. <h2>Software Is Limited by Complexity</h2>
  130. <p>How useful a piece of software can be is usually limited by its complexity rather than the amount of resources invested in building it.</p>
  131. <p>IT systems are often full of features but are still hated by users because of how confusing they become. In contrast, highly ranked mobile apps tend to be lauded for their simplicity and
  132. intuitiveness. Learning to use software is hard. Beyond a point, new features actually make things worse for users because the accumulated complexity starts to become overwhelming. For example, after serving as the hub of Apple’s media ecosystem for almost 20 years, iTunes was split into three
  133. different apps (for music, podcasts, and TV shows) this year, as its features had grown too complex for one app to handle. From a usability perspective, the limit is not how many features can be implemented, but rather what can fit into a simple intuitive interface.</p>
  134. <p>Even ignoring usability, engineering progress slows to a halt once a project becomes too complex. Each new line of code added to an application has a chance of interacting with every other
  135. line. The bigger an application’s codebase, the more bugs are introduced whenever a new feature is built. Eventually, the rate of work created from new bugs cancels out the rate of work done from feature development. This is known as “technical debt” and is the main challenge in professional software development. It is the reason why many large IT systems have issues that go unfixed for years.
  136. Adding more engineers to the project just adds to the chaos: they start running
  137. faster in place as the codebase keels over from its own weight.</p>
  138. <hr>
  139. <h5><em>
  140. Building good software involves alternating cycles of expanding and reducing complexity.
  141. </em></h5>
  142. <hr>
  143. <p>In such cases, the only way forward is to take a step back to rationalise and
  144. simplify the codebase. The system architecture can be redesigned to limit
  145. unexpected interactions. Non-critical features can be removed even if they
  146. have already been built. Automated tools can be deployed to check for bugs and
  147. badly written code. Bill Gates once said “Measuring programming progress by
  148. lines of code is like measuring aircraft building progress by weight”. Human minds can only handle a finite amount of complexity, so how sophisticated a software system can get depends on
  149. how efficiently this complexity budget is used.</p>
  150. <p>Building good software involves alternating cycles of expanding and reducing complexity. As new features are developed, disorder naturally accumulates in the system. When this messiness
  151. starts to cause problems, progress is suspended to spend time cleaning up. This two-step process is necessary because there is no such thing as platonically good engineering: it depends on your
  152. needs and the practical problems you encounter. Even a simple user interface such as Google’s search bar contains a massive amount of complexity under the surface that cannot be perfected in a single iteration. The challenge is managing this cycle, letting it get messy enough to make meaningful progress,
  153. but not letting it get so complicated that it becomes overwhelming.</p>
  154. <hr>
  155. <h5><em>
  156. There is no such thing as platonically good engineering: it depends on your needs and the
  157. practical problems you encounter.
  158. </em></h5>
  159. <hr>
  160. <h2>Software Is about Developing Knowledge More than Writing Code</h2>
  161. <p>In software development, most ideas are bad; this is not anyone’s fault. It is just
  162. that the number of possible ideas is so large that any particular idea is probably
  163. not going to work, even if it was chosen very carefully and intelligently. To make
  164. progress, you need to start with a bunch of bad ideas, discard the worst, and
  165. evolve the most promising ones. Apple, a paragon of visionary design, goes
  166. through dozens of prototypes before landing on a final product. The final
  167. product may be deceptively simple; it is the intricate knowledge of why this
  168. particular solution was chosen over its alternatives that allows it to be good.</p>
  169. <p>This knowledge continues to be important even after the product is built. If a new
  170. team takes over the code for an unfamiliar piece of software, the software will soon
  171. start to degrade. Operating systems will update, business requirements
  172. will change, and security problems will be discovered that need to be fixed. Handling these subtle errors is often harder than building the software in the first place, since it requires intimate
  173. knowledge of the system’s architecture and design principles.</p>
  174. <p></p>
  175. <p class="small-text">A Conversation with Li Hongyi (Part 2)<br>
  176. <em>Scroll down for more videos</em></p>
  177. <p>In the short term, an unfamiliar development team can address these problems with
  178. stopgap fixes. Over time though, new bugs accumulate due to the makeshift nature
  179. of the additional code. User interfaces become confusing due to mismatched
  180. design paradigms, and system complexity increases as a whole. Software should be
  181. treated not as a static product, but as a living manifestation of the development
  182. team’s collective understanding.</p>
  183. <hr>
  184. <h5><em>
  185. Software should be treated not as a static product, but as a
  186. living manifestation of the development team’s collective understanding.
  187. </em></h5>
  188. <hr>
  189. <p>This is why relying on external vendors for your core software development is
  190. difficult. You may get a running system and its code, but the invaluable knowledge
  191. of how it is built and what design choices were made leaves your organisation.
  192. This is also why handing a system over to new vendors for “maintenance” often
  193. causes problems. Even if the system is very well documented, some knowledge
  194. is lost every time a new team takes over. Over the years, the system becomes a
  195. patchwork of code from many different authors. It becomes harder and harder
  196. to keep running; eventually, there is no one left who truly understands how
  197. it works.</p>
  198. <p>For your software to keep working well in the long term, it is important to
  199. have your staff learning alongside the external help to retain critical engineering
  200. knowledge in your organisation.</p>
  201. <h2>3 Principles for Good Software Development</h2>
  202. <h4>1. Start as Simple as Possible</h4>
  203. <p>Projects that set out to be a “one-stop
  204. shop” for a particular domain are often
  205. doomed. The reasoning seems sensible
  206. enough: What better way to ensure your
  207. app solves people’s problems than by
  208. having it address as many as possible?
  209. After all, this works for physical stores
  210. such as supermarkets. The difference is
  211. that while it is relatively easy to add a
  212. new item for sale once a physical store
  213. is set up, an app with twice as many
  214. features is more than twice as hard to
  215. build and much harder to use.</p>
  216. <p>Building good software requires focus:
  217. starting with the simplest solution that
  218. could solve the problem. A well-made
  219. but simplistic app never has problems
  220. adding necessary features. But a big IT
  221. system that does a lot of things poorly
  222. is usually impossible to simplify and
  223. fix. Even successful “do it all” apps like
  224. WeChat, Grab, and Facebook started
  225. out with very specific functionality and
  226. only expanded after they had secured
  227. their place. Software projects rarely
  228. fail because they are too small; they fail
  229. because they get too big.</p>
  230. <hr>
  231. <h5><em>
  232. Software projects rarely fail because they
  233. are too small; they fail because they get too big.
  234. </em></h5>
  235. <hr>
  236. <p>Unfortunately, keeping a project focused
  237. is very hard in practice: just gathering
  238. the requirements from all stakeholders
  239. already creates a huge list of features.</p>
  240. <p></p>
  241. <p class="small-text">A Conversation with Li Hongyi (Part 3)<br>
  242. <em>Scroll down for last video</em></p>
  243. <p>One way to manage this bloat is by
  244. using a priority list. Requirements are
  245. all still gathered, but each are tagged
  246. according to whether they are absolutely
  247. critical features, high-value additions,
  248. or nice-to-haves. This creates a much
  249. lower-tension planning process because
  250. features no longer need to be explicitly
  251. excluded. Stakeholders can then more
  252. sanely discuss which features are the
  253. most important, without worrying about
  254. something being left out of the project.
  255. This approach also makes explicit the
  256. trade-offs of having more features.
  257. Stakeholders who want to increase
  258. the priority for a feature have to also
  259. consider what features they are willing
  260. to deprioritise. Teams can start on the
  261. most critical objectives, working their way
  262. down the list as time and resources allow.</p>
  263. <p>We followed a similar process for all
  264. our most successful apps. Form.gov.sg
  265. started out as a manual Outlook Macro
  266. that took us six hours to set up for
  267. our first user but today has processed
  268. about a million public submissions.
  269. Data.gov.sg started out as a direct copy
  270. of an open source project and has since
  271. grown to over 300,000 monthly visits.
  272. Parking.sg had a massive list of almost
  273. 200 possible features that we never
  274. got around to building but still has over
  275. 1.1 million users today. These systems
  276. are well received not in spite of their
  277. simplicity but because of it.</p>
  278. <h4>2. Seek Out Problems and Iterate</h4>
  279. <p>In truth, modern software is so complicated and changes so rapidly that no amount of
  280. planning will eliminate all shortcomings. Like writing a good paper, awkward
  281. early drafts are necessary to get a feel of what the final paper should be. To
  282. build good software, you need to first build bad software, then actively seek out problems to improve on your solution.</p>
  283. <p>This starts with something as simple as talking to the actual people you are trying to help. The goal is to understand the root problem you want to solve and avoid jumping to a solution based just on preconceived biases. When we first started on Parking.sg, our hypothesis was that enforcement officers found it frustrating to have to keep doing the mental calculations regarding paper coupons. However, after spending just one afternoon with an experienced officer, we discovered that
  284. doing these calculations was actually quite simple for someone doing it professionally. That single conversation saved us months of potentially wasted effort and let us refocus our project on helping drivers instead. </p>
  285. <p>Beware of bureaucratic goals masquerading as problem statements. “Drivers feel frustrated when dealing with parking coupons” is a problem. “We need to build an app for drivers as part of our Ministry Family Digitisation Plans” is not. “Users are annoyed at how hard it is to find information on government websites” is a problem. “As part of the Digital Government Blueprint, we need to rebuild our websites to conform to the new design service standards” is not. If our end goal is to make citizens’ lives better, we need to explicitly acknowledge the things that are making their lives worse.</p>
  286. <p>Having a clear problem statement lets you experimentally test the viability of different solutions that are too hard to determine theoretically. Talking to a chatbot may not be any easier than navigating a website, and users may not want to install yet another app on their phones no matter how secure it makes the country. With software, apparently obvious solutions often have fatal flaws that do not show up until they are put to use. The aim is not yet to build the final product, but to first identify these problems as quickly and as cheaply as possible. Non-functional mock-ups to test interface designs. Semi-functional mock-ups to try different features. Prototype code, written hastily, could help garner feedback more quickly. Anything created at this stage should be treated as disposable. The desired output
  287. of this process is not the code written, but a clearer understanding of what the right thing to build is.</p>
  288. <hr>
  289. <h5><em>
  290. Beware of bureaucratic goals masquerading as problem statements. If our end goal is to make citizens’ lives better, we need to explicitly acknowledge the things that are making their lives worse.
  291. </em></h5>
  292. <hr>
  293. <p>With a good understanding of the right solution, you can start work on building the actual product. You stop exploring new ideas and narrow down to identifying problems with your particular implementation. Begin with a small number of testers who will quickly spot the obvious bugs that need to be fixed. As problems are addressed, you can increasingly open up to a larger pool who will find more esoteric issues.</p>
  294. <p>Most people only give feedback once. If you start by launching to a large audience, everyone will give you the same obvious feedback and you’ll have nowhere to go from there. Even the best product ideas built by the best engineers will start out with significant issues. The aim is to repeatedly refine the output,
  295. sanding down rough edges until a good product emerges.</p>
  296. <p>Even after all this iteration, after launch is when problems with a product matter
  297. the most. A problem that happens only 0.1% of the time may not get noticed
  298. during testing. But once you have a million users, every day the problem
  299. goes unresolved is a thousand more angry people you have to deal with. You need to fix problems caused by new mobile devices, network outages, or security attacks before they cause
  300. substantial harm to your users. With Parking.sg we built a series of secondary
  301. systems that continuously check the main system for any discrepancies in
  302. payments, duplicate parking sessions, and application crashes. Building up
  303. an “immune system” over time lets you avoid being overwhelmed as new issues
  304. inevitably come up.</p>
  305. <p>Overall, the approach is to use these different feedback loops to efficiently
  306. identify problems. Small feedback loops allow for quick and easy correction
  307. but miss out on broader issues. Large feedback loops catch broader issues but
  308. are slow and expensive. You want to use both, resolving as much as possible with
  309. tight loops while still having wide loops to catch unexpected errors. Building
  310. software is not about avoiding failure; it is about strategically failing as fast
  311. as possible to get the information you need to build something good.</p>
  312. <h4>3. Hire the Best Engineers You Can</h4>
  313. <p>The key to having good engineering is having good engineers. Google,
  314. Facebook, Amazon, Netflix, and Microsoft all run a dizzying number of the largest
  315. technology systems in the world, yet, they famously have some of the most
  316. selective interview processes while still competing fiercely to recruit the strongest
  317. candidates. There is a reason that the salaries for even fresh graduates have
  318. gone up so much as these companies have grown, and it is not because they
  319. enjoy giving away money.</p>
  320. <p>Both Steve Jobs and Mark Zuckerberg have said that the best engineers are at
  321. least 10 times more productive than an average engineer. This is not because
  322. good engineers write code 10 times faster. It is because they make better
  323. decisions that save 10 times the work.</p>
  324. <p>A good engineer has a better grasp of
  325. existing software they can reuse, thus
  326. minimising the parts of the system they
  327. have to build from scratch. They have
  328. a better grasp of engineering tools,
  329. automating away most of the routine
  330. aspects of their own job. Automation
  331. also means freeing up humans to work
  332. on solving unexpected errors, which the
  333. best engineers are disproportionately
  334. better at. Good engineers themselves
  335. design systems that are more robust
  336. and easier to understand by others.
  337. This has a multiplier effect, letting their
  338. colleagues build upon their work much
  339. more quickly and reliably. Overall, good
  340. engineers are so much more effective
  341. not because they produce a lot more
  342. code, but because the decisions they
  343. make save you from work you did not
  344. know could be avoided.</p>
  345. <p></p>
  346. <p class="small-text">A Conversation with Li Hongyi (Part 4)</p>
  347. <p>This also means that small teams of the
  348. best engineers can often build things
  349. faster than even very large teams of
  350. average engineers. They make good
  351. use of available open source code and
  352. sophisticated cloud services, and offload
  353. mundane tasks onto automated testing
  354. and other tools, so they can focus on the creative problem-solving aspects of
  355. the job. They rapidly test different ideas
  356. with users by prioritising key features
  357. and cutting out unimportant work. This
  358. is the central thesis of the classic book
  359. “The <em>Mythical Man-Month</em>”<a href="#notes"><sup>1</sup></a>: in general,
  360. adding more software engineers does
  361. not make a project go faster, it only
  362. makes it grow bigger.</p>
  363. <hr>
  364. <h5><em>
  365. Building software is not about avoiding failure; it is about strategically failing as fast as possible to get the information you need to build something good.
  366. </em></h5>
  367. <hr>
  368. <p>Smaller teams of good engineers will
  369. also create fewer bugs and security
  370. problems than larger teams of average
  371. engineers. Similar to writing an essay, the
  372. more authors there are, the more coding
  373. styles, assumptions, and quirks there
  374. are to reconcile in the final composite
  375. product, exposing a greater surface area
  376. for potential issues to arise. In contrast,
  377. a system built by a smaller team of
  378. good engineers will be more concise,
  379. coherent, and better understood by
  380. its creators. You cannot have security
  381. without simplicity, and simplicity is rarely
  382. the result of large-scale collaborations.</p>
  383. <p>The more collaborative an engineering
  384. effort, the better the engineers need
  385. to be. Problems in an engineer’s code
  386. affect not just his work but that of his
  387. colleagues as well. In large projects,
  388. bad engineers end up creating more
  389. work for one another, as errors and
  390. poor design choices snowball to create
  391. massive issues. Big projects need to
  392. be built on solid reliable code modules
  393. in an efficient design with very clear
  394. assumptions laid out. The better your
  395. engineers, the bigger your system can
  396. get before it collapses under its own
  397. weight. This is why the most successful
  398. tech companies insist on the best talent
  399. despite their massive size. The hard limit
  400. to system complexity is not the quantity
  401. of engineering effort, but its quality.</p>
  402. <h2>Conclusion</h2>
  403. <p>Good software development starts
  404. with building a clear understanding of
  405. the problem you want to solve. This
  406. lets you test many possible solutions
  407. and converge on a good approach.
  408. Development is accelerated by reusing
  409. the right open source code and cloud
  410. services, granting immediate access
  411. to established software systems and
  412. sophisticated new technology. The
  413. development cycle alternates between
  414. exploration and consolidation, quickly
  415. and messily progressing on new ideas,
  416. then focusing and simplifying to keep
  417. the complexity manageable. As the
  418. project moves forward, it gets tested
  419. with successively larger groups of people
  420. to eliminate increasingly uncommon
  421. problems. Launching is when the real work
  422. ramps up for a good development team:
  423. layers of automated systems should be
  424. built to handle issues quickly and prevent
  425. harm to actual users. Ultimately, while
  426. there are infinite intricacies to software
  427. development, understanding this process
  428. provides a basis to tackle the complexities
  429. of how to build good software.</p>
  430. </article>
  431. <hr>
  432. <footer>
  433. <p>
  434. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  435. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
  436. </svg> Accueil</a> •
  437. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  438. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-rss2"></use>
  439. </svg> Suivre</a> •
  440. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  441. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-user-tie"></use>
  442. </svg> Pro</a> •
  443. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  444. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-mail"></use>
  445. </svg> Email</a> •
  446. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  447. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-hammer2"></use>
  448. </svg> Légal</abbr>
  449. </p>
  450. <template id="theme-selector">
  451. <form>
  452. <fieldset>
  453. <legend><svg class="icon icon-brightness-contrast">
  454. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-brightness-contrast"></use>
  455. </svg> Thème</legend>
  456. <label>
  457. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  458. </label>
  459. <label>
  460. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  461. </label>
  462. <label>
  463. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  464. </label>
  465. </fieldset>
  466. </form>
  467. </template>
  468. </footer>
  469. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  470. <script>
  471. function loadThemeForm(templateName) {
  472. const themeSelectorTemplate = document.querySelector(templateName)
  473. const form = themeSelectorTemplate.content.firstElementChild
  474. themeSelectorTemplate.replaceWith(form)
  475. form.addEventListener('change', (e) => {
  476. const chosenColorScheme = e.target.value
  477. localStorage.setItem('theme', chosenColorScheme)
  478. toggleTheme(chosenColorScheme)
  479. })
  480. const selectedTheme = localStorage.getItem('theme')
  481. if (selectedTheme && selectedTheme !== 'undefined') {
  482. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  483. }
  484. }
  485. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  486. window.addEventListener('load', () => {
  487. let hasDarkRules = false
  488. for (const styleSheet of Array.from(document.styleSheets)) {
  489. let mediaRules = []
  490. for (const cssRule of styleSheet.cssRules) {
  491. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  492. continue
  493. }
  494. // WARNING: Safari does not have/supports `conditionText`.
  495. if (cssRule.conditionText) {
  496. if (cssRule.conditionText !== prefersColorSchemeDark) {
  497. continue
  498. }
  499. } else {
  500. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  501. continue
  502. }
  503. }
  504. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  505. }
  506. // WARNING: do not try to insert a Rule to a styleSheet you are
  507. // currently iterating on, otherwise the browser will be stuck
  508. // in a infinite loop…
  509. for (const mediaRule of mediaRules) {
  510. styleSheet.insertRule(mediaRule.cssText)
  511. hasDarkRules = true
  512. }
  513. }
  514. if (hasDarkRules) {
  515. loadThemeForm('#theme-selector')
  516. }
  517. })
  518. </script>
  519. </body>
  520. </html>