<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Charles Szilagyi</title>
    <description>The latest articles on DEV Community by Charles Szilagyi (@thekarel).</description>
    <link>https://dev.to/thekarel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F159781%2Fe837b4da-4edb-4805-930b-ed7533b50c81.png</url>
      <title>DEV Community: Charles Szilagyi</title>
      <link>https://dev.to/thekarel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thekarel"/>
    <language>en</language>
    <item>
      <title>End-to-end Type Safety in Clean Architecture</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Fri, 22 May 2020 10:23:56 +0000</pubDate>
      <link>https://dev.to/thekarel/end-to-end-type-safety-in-clean-architecture-48la</link>
      <guid>https://dev.to/thekarel/end-to-end-type-safety-in-clean-architecture-48la</guid>
      <description>&lt;p&gt;Let's create a completely type-safe web application in a Clean Architecture using a couple of modern libraries. Such systems are orders of magnitude more reliable than the untyped counterparts. Plus, they are easier to understand, maintain and refactor. Tech: TypeScript, GraphQL, MongoDB, React.&lt;/p&gt;

&lt;p&gt;💡 The sample code is on Github: &lt;a href="https://github.com/thekarel/best-practices-example" rel="noopener noreferrer"&gt;https://github.com/thekarel/best-practices-example&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  End to End Type Safety
&lt;/h1&gt;

&lt;p&gt;In this post I show you how to build a full-stack web application that is type-safe across all layers of the architecture: from the domain models to the services, repositories, the HTTP transport layer (GraphQL) and client-side UI. It's more than just typing up every interface in the codebase: in this example, all significant interfaces and types are derived from higher-order ones - usually from the &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/architecture/domain" rel="noopener noreferrer"&gt;domain modules&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is only a single source of truth for types&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means that changes to high-level interfaces cascade through the whole stack. The type checker will be able to spot a mismatch in any one of the layers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg6gsqbuxtq3w81u5kl6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg6gsqbuxtq3w81u5kl6c.png" title="Github code repository" alt="Github code repository" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Benefits
&lt;/h1&gt;

&lt;p&gt;The practical benefits are pretty significant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The linter warns you of potential bugs before you even run a test or let alone build the app&lt;/li&gt;
&lt;li&gt;You need to write far fewer &lt;a href="https://thekarel.gitbook.io/best-practices/testing/purpose/unit" rel="noopener noreferrer"&gt;unit tests&lt;/a&gt; than otherwise because the whole codebase relies on interconnected type definitions.&lt;/li&gt;
&lt;li&gt;The codebase is easier to understand as the same interfaces are repeated (maybe with slight modifications)&lt;/li&gt;
&lt;li&gt;Since everything is typed the code is &lt;a href="https://thekarel.gitbook.io/best-practices/source-code/comments" rel="noopener noreferrer"&gt;self-documenting&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;When you change the code - fix, refactor or improve - you get &lt;em&gt;instant feedback&lt;/em&gt; about the health of your codebase in the IDE or by running &lt;code&gt;tsc&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Experience shows that even large refactoring can be successfully done on such codebase, solely based on static type checking. Of course, it is not a substitute for &lt;a href="https://thekarel.gitbook.io/best-practices/testing/purpose/e2e" rel="noopener noreferrer"&gt;End-to-end tests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All in all, I think such stack eliminates some significant sources of bugs that would otherwise exist because the codebase complexity exceeds a limit. We're incapable of remembering every data shape, type and interface. Apart from fewer bugs, you'd also benefit from higher confidence and faster development throughput. Win-win?&lt;/p&gt;

&lt;h1&gt;
  
  
  Clean Architecture TL;DR
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/architecture" rel="noopener noreferrer"&gt;architecture&lt;/a&gt; of this example follows &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt; principles.&lt;/p&gt;

&lt;p&gt;This, in a nutshell, means that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The app is sliced into layers, starting from the deepest: domain (entities), services (use cases), transport (GraphQL in this case), repository (abstraction over MongoDB), UI (React, closest to the user)&lt;/li&gt;
&lt;li&gt;There is a &lt;em&gt;strictly unidirectional dependency arrow&lt;/em&gt;: layers that are deeper in the stack can never refer to any code in outer layers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second rule implies that the domain module will never import or refer to anything defined in other layers. The services receive "tools" to get and save data (etc.) via dependency injection. The repository can know about domain entities (but not much else). The transport layer is a smart cookie and knows about the domain, services and repositories (this is the dependency injection root). The UI, ideally, is limited to the GraphQL types, and maybe the domain entities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7dztbl7gdm1xdfhbge6f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7dztbl7gdm1xdfhbge6f.jpg" title="The original Clean Architecture diagram" alt="The original Clean Architecture diagram" width="772" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The original Clean Architecture diagram. Image from &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/architecture" rel="noopener noreferrer"&gt;https://thekarel.gitbook.io/best-practices/the-big-picture/architecture&lt;/a&gt; for a detailed treatment.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tech Stack
&lt;/h1&gt;

&lt;p&gt;Reminder: there is a complete example available at &lt;a href="https://github.com/thekarel/best-practices-example" rel="noopener noreferrer"&gt;https://github.com/thekarel/best-practices-example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The technologies and libraries I use are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/apollographql/apollo-server" rel="noopener noreferrer"&gt;Apollo Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MichalLytek/type-graphql" rel="noopener noreferrer"&gt;TypeGraphQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dotansimha/graphql-code-generator" rel="noopener noreferrer"&gt;GraphQL Codegen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nearform/graphql-hooks" rel="noopener noreferrer"&gt;GraphQL Hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mongodb.github.io/node-mongodb-native/" rel="noopener noreferrer"&gt;MongoDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I assume you are relatively familiar with most of these tools already. I'll focus on two libraries that are probably not so widely used and also highlight a couple of essential solutions.&lt;/p&gt;

&lt;p&gt;Let's look at each layer one by one and see how this stack hangs together.&lt;/p&gt;

&lt;h1&gt;
  
  
  Layers
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Domain
&lt;/h2&gt;

&lt;p&gt;Technically this is the simplest slice of the stack. The entities are pure TypeScript interfaces. For example, an &lt;code&gt;Order&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Cupcake&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../cupcake/Cupcake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;deliveryAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Cupcake&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The corresponding &lt;code&gt;Cupcake&lt;/code&gt; is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Feature&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Kind&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Cupcake&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Kind&lt;/span&gt;
  &lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The critical fact is that all subsequent layers will refer back to these definitions in some shape or form.&lt;/p&gt;

&lt;h2&gt;
  
  
  Services
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/architecture/services" rel="noopener noreferrer"&gt;Service layer&lt;/a&gt;, also known as Use Cases defines the possible operations on our entities. In this example, these include creating and reading &lt;code&gt;Order&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;The domain entities are very abstract, but you might be thinking: creating an order is a concrete operation and must be able to talk to a database etc. This fact seems to contradict the dependency arrow rule mentioned above.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dependency Arrow Rule: Layers that are deeper in the stack can never refer to any code in outer layers&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The solution is to define dependency interfaces in the Service layer. For example, the &lt;code&gt;OrderService&lt;/code&gt; defines an &lt;code&gt;OrderRepository&lt;/code&gt; interface. This way the service itself will not have to know anything about the way orders are stored, but can dictate the shape of data going in and coming out of a repository - the rest is an implementation detail, from this point of view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cupcake/domain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;OrderRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In terms of end to end type safety, please note how the &lt;code&gt;save&lt;/code&gt; method takes a &lt;em&gt;domain Order&lt;/em&gt; and similarly how the &lt;code&gt;load&lt;/code&gt; method returns one. This ensures that we can use different storage methods without breaking the contract (see below).&lt;/p&gt;

&lt;p&gt;The domain interfaces reappear in similar ways across the whole stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repository
&lt;/h2&gt;

&lt;p&gt;As hinted above, the &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/architecture/persistence" rel="noopener noreferrer"&gt;repository is a data persistence abstraction&lt;/a&gt;. Since it implements a higher-level interface definition, we can use different storage strategies in our app depending on the circumstances. Compare the following two repository implementations: one saves into memory, the other into a real database:&lt;/p&gt;

&lt;h3&gt;
  
  
  OrderRepositoryMemory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;OrderRepository&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cupcake/services&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cupcake/domain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderRepositoryMemory&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OrderRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  OrderRepositoryMongo
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cupcake/domain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;OrderRepository&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cupcake/services&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderRepositoryMongo&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OrderRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MongoClient&lt;/span&gt;
  &lt;span class="nx"&gt;dbName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cupcakes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;collectionName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cupcakes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;useUnifiedTopology&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Connect first&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// etc&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Look at the example codebase to &lt;a href="https://github.com/thekarel/best-practices-example/blob/master/modules/graph/src/getProductionContainer.ts#L13" rel="noopener noreferrer"&gt;see how different repositories are injected&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another equally important fact to note is that all type definitions are picked up from the domain and services layers.&lt;/p&gt;

&lt;p&gt;Probably the most significant feature in the type safety context is the fact that we enforce the database documents' shape to match the domain entities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is to ensure the primary rule of persistence in Clean Architecture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A repository takes a domain entity and returns a domain entity or a list of entities&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The type-safety of the database layer itself is an important fact: it guarantees that the data entering our system (from the outside world) will match the expected domain shape. In other words, we ensure that everything inside the application boundaries is of known shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL
&lt;/h2&gt;

&lt;p&gt;The example codebase uses GraphQL as the &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/architecture/http" rel="noopener noreferrer"&gt;transport layer solution&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;GraphQL types are sometimes defined using the &lt;a href="https://graphql.org/learn/schema/#type-language" rel="noopener noreferrer"&gt;"GraphQL schema language"&lt;/a&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Customer {
  name: String!
  address: String!
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the schema language has one serious disadvantage: it's not possible to refer to domain types using GraphQL's schema. It's time to look at...&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeGraphQL
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff8m3fhh9w8cbj2ha0mtc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff8m3fhh9w8cbj2ha0mtc.png" title="TypeGraphQL" alt="TypeGraphQL" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://typegraphql.com/" rel="noopener noreferrer"&gt;TypeGraphQL&lt;/a&gt; allows us to define GraphQL schemas using TypeScript classes. Using &lt;code&gt;implements&lt;/code&gt; we can then refer back to domain interfaces. For example, this is how a &lt;code&gt;Cupcake&lt;/code&gt; interface looks like in the &lt;a href="https://github.com/thekarel/best-practices-example/tree/master/modules/graph/src" rel="noopener noreferrer"&gt;example Graph&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Cupcake&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;DomainCupcake&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;DomainOrder&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cupcake/domain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;type-graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Cupcake&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../cupcake/Cupcake&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;DomainOrder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;customerName&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;deliveryAddress&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Cupcake&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DomainCupcake&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/thekarel/best-practices-example/blob/master/modules/graph/src/generateSchema.ts" rel="noopener noreferrer"&gt;Generating the final schema&lt;/a&gt; from these classes is trivial (don't worry about the container, it has nothing to do with type-safety):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;AwilixContainer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;awilix&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buildSchemaSync&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;type-graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;OrderResolver&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./order/OrderResolver&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generateSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AwilixContainer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;buildSchemaSync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;resolvers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;OrderResolver&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Graph imports the domain type definitions and turns them into strong guarantees: anyone sending a &lt;code&gt;Cupcake&lt;/code&gt; to the server must conform to the domain schema (or the request is rejected). What we achieve with this is significant the same way as it was for the repository: the data coming into our system from the outside world is guaranteed to match our expectations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The data coming into our system from the outside world is guaranteed to match our expectations&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  UI
&lt;/h2&gt;

&lt;p&gt;The example app uses a React UI - but any UI library would work.&lt;/p&gt;

&lt;p&gt;The crucial question is instead, how do we map from our Graph or domain entities to definitions that are useable in the UI?&lt;/p&gt;

&lt;p&gt;Ideally, the UI only knows about the Graph interfaces: these are the "things" that are sent towards the client, and in turn, this is what the client sends back.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ideally, the UI only knows about the Graph interfaces&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;GraphQL being what it is, there are other, more intricate questions concerning queries and mutations - it can get complicated quickly. Manually copying all these interfaces from Grap to the UI codebase, and keeping them updated is hopeless.&lt;/p&gt;

&lt;p&gt;Hence, we look at the last piece of the puzzle: generating static TypeScript types from GraphQL schemas.&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL Codegen
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo12krkl1i58l6j9qh0gh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fo12krkl1i58l6j9qh0gh.png" title="GraphQL Code Generator" alt="GraphQL Code Generator" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://graphql-code-generator.com/" rel="noopener noreferrer"&gt;GraphQL Code Generator&lt;/a&gt; is a CLI tool that can generate TypeScript typings out of a GraphQL schema.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The implementation is relatively simple and it only touches the UI project.&lt;/p&gt;

&lt;p&gt;First, define a &lt;a href="https://github.com/thekarel/best-practices-example/blob/master/modules/ui/codegen.yml" rel="noopener noreferrer"&gt;configuration file&lt;/a&gt; in &lt;code&gt;ui/codegen.yml\&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8888/&lt;/span&gt;
&lt;span class="na"&gt;generates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;src/graphQLTypes.ts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;afterOneFileWrite&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;prettier --write&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript-operations&lt;/span&gt;
&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;namingConvention&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enumValues&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keep&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a command to &lt;a href="https://github.com/thekarel/best-practices-example/blob/master/modules/ui/package.json" rel="noopener noreferrer"&gt;package.json&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typegen"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"graphql-codegen"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you know that the GraphQL schema has changed - this is &lt;a href="https://thekarel.gitbook.io/best-practices/constraints/monorepo" rel="noopener noreferrer"&gt;easy in a monorepo&lt;/a&gt; - run the &lt;code&gt;typegen&lt;/code&gt; command in the UI to generate a local type definition of the Graph types. You commit these to the codebase just like any hand-written code.&lt;/p&gt;

&lt;p&gt;Having access to these types enables UI components to refer to the Graph types when &lt;a href="https://github.com/thekarel/best-practices-example/blob/master/modules/ui/src/dashboard/DashboardContainer.tsx" rel="noopener noreferrer"&gt;making a request or creating a payload&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MutationCreateOrderArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../graphQLTypes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// later&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fetchOrders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ordersFetchStatus&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useManualQuery&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orders&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ordersQuery&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetchOrders&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;


  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dumbOrderArgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MutationCreateOrderArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;deliveryAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New York&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mr. Muffin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;savoury&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sugarFree&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;One&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sweet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vegan&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Two&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sweet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;features&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exclusive&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Three&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The End
&lt;/h1&gt;

&lt;p&gt;As with any code example, this is a slight simplification. Life is always a bit different and undoubtedly more challenging. I haven't touched the topic of evolving interfaces (data shapes), for example. Still, I think these ideas and tools provide a solid foundation to build on.&lt;/p&gt;

&lt;p&gt;Relying on clean architecture and a type-safe codebase will make the products we make better and our lives more comfortable at the same time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The more complex you build, the more type safety you need!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have I missed something? Please &lt;a href="https://twitter.com/thekarel" rel="noopener noreferrer"&gt;let me know&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>architecture</category>
      <category>graphql</category>
      <category>react</category>
    </item>
    <item>
      <title>Using OS X Without the Mouse</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Mon, 18 May 2020 07:40:21 +0000</pubDate>
      <link>https://dev.to/thekarel/using-os-x-without-the-mouse-47ic</link>
      <guid>https://dev.to/thekarel/using-os-x-without-the-mouse-47ic</guid>
      <description>&lt;p&gt;Moving away from the trackpad or mouse is not a one time toggle though - it's a process that takes time for everyone. Let's get started on macOS and see what tools are out there to help you along your journey.&lt;/p&gt;

&lt;h1&gt;
  
  
  Learn Keyboard Shortcuts
&lt;/h1&gt;

&lt;p&gt;This one is too obvious, still often overlooked: if you repeatedly reach for the mouse to do a particular action, try to find the relevant shortcut in your app.&lt;/p&gt;

&lt;p&gt;For system-wide hotkeys, check out the &lt;a href="https://support.apple.com/en-us/HT201236" rel="noopener noreferrer"&gt;official Mac keyboard shortcuts&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browse commands
&lt;/h2&gt;

&lt;p&gt;A powerful key combination you might want to keep in mind is &lt;code&gt;⌘⇧\&lt;/code&gt;: it lets you search all the shortcuts of the current app plus run the commands, or simply navigate the menus with the keyboard.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the &lt;code&gt;⌘⇧\&lt;/code&gt; shortcut to navigate app menus and run commands&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fc0fd3ae88f5e6f1326ad8b1aa66926d4%2Fkeyboardonly-01.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fc0fd3ae88f5e6f1326ad8b1aa66926d4%2Fkeyboardonly-01.gif" title="Use the ⌘⇧\ shortcut to navigate app menus and run commands" alt="Use the ⌘⇧\ shortcut to navigate app menus and run commands" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CheatSheet
&lt;/h2&gt;

&lt;p&gt;There is a free app called &lt;a href="https://mediaatelier.com/CheatSheet/?lang=en" rel="noopener noreferrer"&gt;CheatSheet&lt;/a&gt; that can show you all the shortcuts available in the current window by holding the command &lt;code&gt;⌘&lt;/code&gt; key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2F7e2d07a0e833465ec0045c6e5be8e7b4%2F04bec%2Fkeyboardonly-02-ch.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2F7e2d07a0e833465ec0045c6e5be8e7b4%2F04bec%2Fkeyboardonly-02-ch.jpg" title="CheatSheet showing Sketch shortcuts" alt="CheatSheet showing Sketch shortcuts" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can even print the hotkey list for future reference if you like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take it easy
&lt;/h2&gt;

&lt;p&gt;You might be overwhelmed at first, but remember: learning takes time. Don't try to memorise every key combination at once. Just let the ones you often use become second nature, then pick up new ones as you go.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Scary but Powerful: Vim mode 🙀
&lt;/h1&gt;

&lt;p&gt;Vim is the infamous editor you &lt;a href="https://github.com/hakluke/how-to-exit-vim" rel="noopener noreferrer"&gt;can't get out of&lt;/a&gt;, right? Well, I'm not saying you should use Vim as your primary editor. There are better alternatives nowadays IMO, although it's still the most powerful text editor probably and &lt;a href="https://thoughtbot.com/upcase/vim" rel="noopener noreferrer"&gt;it's not that hard to pick up&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What I'm suggesting though, is to learn the basic movement and command keys of &lt;em&gt;Vim mode&lt;/em&gt;. It's a brilliant, comfortable and efficient way of using the keyboard. It is probably the fastest way to deal with text editing and writing source code. It has been around for 28 years since Vim came out (!), and seems like there are no significantly better alternatives for now.&lt;/p&gt;

&lt;p&gt;You can get started with learning just a handful of shortcuts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move left, down, up, right: &lt;code&gt;h&lt;/code&gt;, &lt;code&gt;j&lt;/code&gt;, &lt;code&gt;k&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Go to the top of the document: &lt;code&gt;gg&lt;/code&gt; (&lt;code&gt;G&lt;/code&gt; takes you to the end).&lt;/li&gt;
&lt;li&gt;Go to &lt;em&gt;insert mode&lt;/em&gt; so you can type any text: &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Exit insert mode and go back to "navigate" again: &lt;code&gt;ESC&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't believe the hype; it's not that difficult 🤓&lt;/p&gt;

&lt;p&gt;There are countless more tricks, shortcuts and all sorts of magic you can do with Vim. The main thing to appreciate though is that the modal nature of Vim mode allows you to keep your hands on the &lt;em&gt;home row&lt;/em&gt; of the keyboard so that you can touch-type without interruption. You will need to pick up the mouse a lot less often.&lt;/p&gt;

&lt;p&gt;As you'll see below, a lot of new solutions borrow from Vim's keybindings. Even Gmail has matching hotkeys!&lt;/p&gt;

&lt;h2&gt;
  
  
  Vim mode in VS Code
&lt;/h2&gt;

&lt;p&gt;Probably all source code editors and IDEs support Vim mode in some form. I use VS Code nowadays (&lt;a href="https://charlesagile.com/debug-series-nodejs-browser-javascript" rel="noopener noreferrer"&gt;who knew?&lt;/a&gt;) and probably the first extension I have installed was &lt;a href="https://marketplace.visualstudio.com/items?itemName=vscodevim.vim" rel="noopener noreferrer"&gt;VSCodeVim&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2Ff28b51275e906b885d0c3fbac06d36f4%2F42cbc%2Fkeyboardonly%252003%2520vsvim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2Ff28b51275e906b885d0c3fbac06d36f4%2F42cbc%2Fkeyboardonly%252003%2520vsvim.png" title="VSCodeVim extension for VS Code" alt="VSCodeVim extension for VS Code" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;VSCodeVim is a Vim emulator for Visual Studio Code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Combined with the flexible shortcuts of the IDE itself, VSCodeVim allows me to create and change source code fast - significantly faster than otherwise. The navigation inside and between files is also brilliant.&lt;/p&gt;

&lt;p&gt;For a  quick overview, check out Using VSCode with the VIM Extension by Richard Bagshaw:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/44snngEzNMQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Some of my favourite and most often used features are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gd&lt;/code&gt; jumps to the definition of the symbol (variable, function, import etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gh&lt;/code&gt; displays the linter warning/error on the current line.&lt;/li&gt;
&lt;li&gt;Jump to the line I'm looking at by using &lt;a href="https://code.visualstudio.com/updates/v1_6#_improvements-to-linenumber-and-whitespace-settings" rel="noopener noreferrer"&gt;relative line numbers&lt;/a&gt; and typing something like &lt;code&gt;15k&lt;/code&gt; (15 lines up).&lt;/li&gt;
&lt;li&gt;Being able to change code &lt;em&gt;inside&lt;/em&gt; parens, curly braces or an HTML/React tag with &lt;code&gt;ci(&lt;/code&gt;, &lt;code&gt;ci{&lt;/code&gt;, &lt;code&gt;cit&lt;/code&gt; respectively. You can also change the &lt;em&gt;whole block&lt;/em&gt; with &lt;code&gt;ca(&lt;/code&gt;, &lt;code&gt;ca{&lt;/code&gt; or &lt;code&gt;cat&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus, the usual, basic editing tricks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding to the beginning or end of a line with &lt;code&gt;I&lt;/code&gt; or &lt;code&gt;A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adding a new line below or above with &lt;code&gt;o&lt;/code&gt; or &lt;code&gt;O&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Copying, deleting or changing the whole line with &lt;code&gt;yy&lt;/code&gt;, &lt;code&gt;dd&lt;/code&gt;, &lt;code&gt;cc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Finding character in the current line with &lt;code&gt;f&lt;/code&gt;, e.g. &lt;code&gt;f(&lt;/code&gt; to jump to the next &lt;code&gt;(&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Clicking on Things with Vimac
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://vimacapp.com/" rel="noopener noreferrer"&gt;Vimac is a fantastic app&lt;/a&gt; by Dexter Leng that allows you to "Stop using your clunky trackpad/mouse now" on Mac OS.&lt;/p&gt;

&lt;p&gt;By pressing a shortcut, you're presented with a "hint" to every interactive element on the screen. Next, you tap the hint keys to simulate a mouse click - without touching the mouse! 🐭&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2F58a35211e9a6d2507e03c8bf91e5c6bd%2F04bec%2Fkeyboardonly%252004%2520vimac.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2F58a35211e9a6d2507e03c8bf91e5c6bd%2F04bec%2Fkeyboardonly%252004%2520vimac.jpg" title="Using Vimac with the Appstore" alt="Using Vimac with the Appstore" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are modifiers to simulate right-click or &lt;code&gt;⌘&lt;/code&gt;-click, plus you can turn on Vim-like scrolling for lists inside apps.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/bah8zhTtAvs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I strongly encourage you to give this gem a try: &lt;a href="https://vimacapp.com" rel="noopener noreferrer"&gt;https://vimacapp.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  XEasyMotion
&lt;/h2&gt;

&lt;p&gt;A little tool I'd also recommend and still use for clicking on the screen is &lt;a href="https://github.com/h2ero/XEasyMotion" rel="noopener noreferrer"&gt;XEasyMotion&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It opens a crosshair on your screen so you can click on anything you'd like, even if it's not interactive. You move the crosshair with &lt;code&gt;hjkl&lt;/code&gt; by the way 😉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcloud.githubusercontent.com%2Fassets%2F1262641%2F16171960%2F62cea4f8-35af-11e6-9a2f-ef074c12bcf9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcloud.githubusercontent.com%2Fassets%2F1262641%2F16171960%2F62cea4f8-35af-11e6-9a2f-ef074c12bcf9.gif" title="XEasyMotion animation" alt="XEasyMotion animation" width="560" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Gif from &lt;a href="https://github.com/h2ero/XEasyMotion" rel="noopener noreferrer"&gt;https://github.com/h2ero/XEasyMotion&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Clicking on Internet Things with Vimium
&lt;/h1&gt;

&lt;p&gt;Another spiritual successor of Vim is &lt;a href="https://vimium.github.io/" rel="noopener noreferrer"&gt;Vimium - The Hacker's Browser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vimium works similarly to Vimac, but inside your browser: after installing the extension for &lt;a href="https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb" rel="noopener noreferrer"&gt;Chrome&lt;/a&gt; or &lt;a href="https://addons.mozilla.org/en-GB/firefox/addon/vimium-ff" rel="noopener noreferrer"&gt;Firefox&lt;/a&gt; you can press a shortcut - &lt;code&gt;f&lt;/code&gt; by default - then type the letters of the hints where you'd like to click.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2Fde7b770da19917add7aae3795d4f1ec8%2F04bec%2Fkeyboardonly%252005%2520vimium.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2Fde7b770da19917add7aae3795d4f1ec8%2F04bec%2Fkeyboardonly%252005%2520vimium.jpg" title="Clicking links on dev.to with Vimium" alt="Clicking links on dev.to with Vimium" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You won't appreciate how easy and comfortable browsing becomes until you give Vimium a try!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/t67Sn0RGK54"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Productivity apps
&lt;/h1&gt;

&lt;p&gt;Of course, there are many power tools out there designed to help simplify your life and make you faster. Here are some of my favourites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launchbar
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://obdev.at/products/launchbar/index.html" rel="noopener noreferrer"&gt;Launchbar&lt;/a&gt; is an application, file, folder (etc.) launcher with fuzzy search, an elegantly simple interface and a &lt;a href="https://obdev.at/products/launchbar/features.html" rel="noopener noreferrer"&gt;staggering amount of features&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After pressing the designated shortcut, you can start typing the name of the "thing" you'd like to open. Launchbar can naturally open applications, files or folders anywhere on your Mac. Plus, there are many other entities you can manage: contacts, calendar events, bookmarks, search engines, songs, calculations, text snippets, data from 3rd party apps and so on. It's a powerful tool 💪!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/7grtC-TA4Rk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The features I'm using the most are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening and switching between apps - it can even replace &lt;code&gt;⌘+TAB&lt;/code&gt;!&lt;/li&gt;
&lt;li&gt;Opening files and folders: every file and folder takes the same time to open, just press a few (fuzzy) letters&lt;/li&gt;
&lt;li&gt;Looking up previous clipboard entries and pasting them again and again&lt;/li&gt;
&lt;li&gt;Use ClipMerge to copy multiple things to the clipboard so I can paste them in one go&lt;/li&gt;
&lt;li&gt;Inserting pre-defined text snippets, so I don't have to repeat myself over and over again - and it works in &lt;em&gt;any&lt;/em&gt; application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've been using Launchbar for over five years now. These nano-optimisations seem to add up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2F85134da84d68b6f3339218ef42c1c5d4%2Fa54a1%2Fkeyboardonly%252006%2520launchbar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcharlesagile.com%2Fstatic%2F85134da84d68b6f3339218ef42c1c5d4%2Fa54a1%2Fkeyboardonly%252006%2520launchbar.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Alfred
&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a href="https://dev.to/euperia/comment/p70l"&gt;@euperia&lt;/a&gt; for drawing my attention to &lt;a href="https://www.alfredapp.com/" rel="noopener noreferrer"&gt;Alfred&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Its like Spotlight on steroids. You can extend it with add-ons to do things like play/pause/skip spotify, generate passwords, perform google searches etc - all without needing to take your hands off the keyboard.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sounds brilliant!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wyePqBBJPiU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyboard Maestro
&lt;/h2&gt;

&lt;p&gt;Finally, a tool that sports a less impressive UX but allows you to automate &lt;em&gt;anything&lt;/em&gt; on your computer: &lt;a href="https://www.keyboardmaestro.com/" rel="noopener noreferrer"&gt;Keyboard Maestro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In their own words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Automate applications or web sites, text or images, simple or complex, on command or scheduled. You can automate virtually anything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one is an advanced tool, and the possibilities are truly limitless - at least I couldn't find the limits yet. Just to highlight a few things you can achieve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remap keys&lt;/li&gt;
&lt;li&gt;Record interactions with an app or website and replay it&lt;/li&gt;
&lt;li&gt;Fill out forms&lt;/li&gt;
&lt;li&gt;Click on images on the screen&lt;/li&gt;
&lt;li&gt;Replay activity for screencasting :)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out a few tips and use cases in this video:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Gy_dBHxqZ94"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Desktop managers
&lt;/h1&gt;

&lt;p&gt;The way macOS manages windows is just plain annoying. By default, new apps appear at random places, overlapping each other, forcing you to move them manually. We can do better than that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Rectangle
&lt;/h2&gt;

&lt;p&gt;When on a smaller screen, I've used &lt;a href="https://www.spectacleapp.com/" rel="noopener noreferrer"&gt;Spectacle&lt;/a&gt; for a very long time. This little tool allows you to snap windows to edges or corners of the screen, or to make them centred or full-screen (and so on), with keyboard shortcuts.&lt;/p&gt;

&lt;p&gt;Recently it was announced that Spectacle is not maintained anymore and apparently &lt;a href="https://github.com/rxhanson/Rectangle" rel="noopener noreferrer"&gt;Rectangle is a great replacement&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/17t0OSziUgY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;With Rectangle, you can optimise the screen real-estate, de-clutter your desktop and quickly snap new apps to your preferred location, all without touching the mouse. A highly recommended tool!&lt;/p&gt;

&lt;h2&gt;
  
  
  Amethyst
&lt;/h2&gt;

&lt;p&gt;When working on a large display, like a 34" ultra-wide monitor, I've found even manual window snapping is sub-optimal. So at the moment, I'm running &lt;a href="https://ianyh.com/amethyst/" rel="noopener noreferrer"&gt;Amethyst&lt;/a&gt; - a tiling window manager for macOS.&lt;/p&gt;

&lt;p&gt;Essentially, when you run a tiling window manager, instead of manually managing the windows, they are positioned automatically on the screen in tiles (surprise!), so they never overlap.&lt;/p&gt;

&lt;p&gt;You can then use keyboard shortcuts to move them around, change the focus etc.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/boPilhScpkY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;While it takes a little getting used to such a desktop, I've found it to be more comfortable so far than having to worry about manually positioning windows repeatedly.&lt;/p&gt;

&lt;p&gt;Do you have any #mouseless tips and tricks you'd share? &lt;a href="https://twitter.com/thekarel" rel="noopener noreferrer"&gt;Let me know!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>osx</category>
      <category>keyboard</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Debug anything: React in TypeScript with Parcel 📦</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Mon, 11 May 2020 06:14:56 +0000</pubDate>
      <link>https://dev.to/thekarel/debug-anything-react-in-typescript-with-parcel-4i15</link>
      <guid>https://dev.to/thekarel/debug-anything-react-in-typescript-with-parcel-4i15</guid>
      <description>&lt;h1&gt;
  
  
  Get the code
&lt;/h1&gt;

&lt;p&gt;You can skip ahead if you already have a React, TypeScript and Parcel project. Otherwise, let's check out the example code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:thekarel/debug-anything.git
&lt;span class="nb"&gt;cd &lt;/span&gt;debug-anything/parcel
yarn &lt;span class="c"&gt;# or npm i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237853-debuganything-06-01-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237853-debuganything-06-01-code.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Code structure
&lt;/h1&gt;

&lt;p&gt;The application itself is elementary: you'll see a list of &lt;a href="https://jsonplaceholder.typicode.com/posts" rel="noopener noreferrer"&gt;fake blog post titles&lt;/a&gt;, clicking on a title will fetch the body of the post and display it above the list.&lt;/p&gt;

&lt;p&gt;The code in this folder is, as usual, kept as simple as possible so that we can focus our attention on the debugger. In a production app, we'd use a &lt;a href="https://thekarel.gitbook.io/best-practices/source-code/folderstructure" rel="noopener noreferrer"&gt;human-friendly folder structure&lt;/a&gt;. The entry point is &lt;code&gt;index.html&lt;/code&gt; which pulls in &lt;code&gt;index.tsx&lt;/code&gt; and runs the basic React app. &lt;/p&gt;

&lt;p&gt;You should focus on the following files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Post.ts &lt;span class="c"&gt;# The Post interface type&lt;/span&gt;
Posts.tsx &lt;span class="c"&gt;# The post-list React component &lt;/span&gt;
index.html &lt;span class="c"&gt;# The entry-point&lt;/span&gt;
index.tsx &lt;span class="c"&gt;# The React app&lt;/span&gt;
postRepository.ts &lt;span class="c"&gt;# Data fetching module&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Less than 100 lines altogether, so don't expect anything revolutionary 😉&lt;/p&gt;

&lt;h1&gt;
  
  
  Parcel
&lt;/h1&gt;

&lt;p&gt;You might be wondering where is the Webpack or Babel configuration file? Well, there's none! Since &lt;a href="https://parceljs.org/" rel="noopener noreferrer"&gt;Parcel&lt;/a&gt; is a zero-configuration bundler, we can just tell it to compile the code, and it Just Works all the time. I find it easier to work with than other solutions like &lt;a href="https://charlesagile.com/debug-create-react-app" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt; as it's so simple and fast. &lt;/p&gt;

&lt;p&gt;In this example, we can bundle the whole React app, written in TypeScript, by simply pointing Parcel to &lt;code&gt;index.html&lt;/code&gt; - and that's all the plumbing we need. &lt;a href="https://charlesagile.com/paying-attention-the-mental-cost-of-development" rel="noopener noreferrer"&gt;One less thing to worry about&lt;/a&gt;. Deserves a star ⭐️ &lt;a href="https://github.com/parcel-bundler/parcel" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt; 👍&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: this example code uses Parcel 2 alpha 3.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Dev server
&lt;/h1&gt;

&lt;p&gt;Let's start the dev server with &lt;code&gt;yarn start&lt;/code&gt; or &lt;code&gt;npm start&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;╰─&lt;span class="nv"&gt;$ &lt;/span&gt;yarn start 
yarn run v1.22.4
&lt;span class="nv"&gt;$ &lt;/span&gt;parcel index.html
ℹ️ Server running at http://localhost:1234
✨ Built &lt;span class="k"&gt;in &lt;/span&gt;548ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you can visit &lt;a href="http://localhost:1234" rel="noopener noreferrer"&gt;http://localhost:1234&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237874-debuganything-06-02-app.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237874-debuganything-06-02-app.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "app" fetches the list of posts on start, then grabs the selected post's title from the server.&lt;/p&gt;

&lt;h1&gt;
  
  
  Configure the debugger
&lt;/h1&gt;

&lt;p&gt;What we'd like to achieve in terms of debugging, is to be able to set breakpoints in VS Code, launch a debug browser and step through the initial list fetch and subsequent remote requests.&lt;/p&gt;

&lt;p&gt;To make this as easy and comfortable as possible, we'll take advantage of the &lt;a href="https://charlesagile.com/vscode-launch-json-and-the-debug-console" rel="noopener noreferrer"&gt;launch.json configuration file&lt;/a&gt;. It's actually all prepared for you 😌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237880-debuganything-06-03-launchjson.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237880-debuganything-06-03-launchjson.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look at &lt;code&gt;.vscode/launch.json&lt;/code&gt; and focus on the React+TS, Parcel section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Debug React, TS, Parcel app in Chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:1234/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"webRoot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/parcel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pathMapping"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"__parcel_source_root"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/parcel"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"skipFiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/parcel/node_modules/**/*.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;node_internals&amp;gt;/**/*.js"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The config is very similar to our &lt;a href="https://charlesagile.com/debug-create-react-app#creating-a-launchjson" rel="noopener noreferrer"&gt;Create React App example&lt;/a&gt;, by the way. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;type&lt;/code&gt; and &lt;code&gt;request&lt;/code&gt; parameters tell VS Code to start debugging in a new Chrome window. It will use an empty profile by the way, without extensions or personal settings.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;name&lt;/code&gt; of the launcher will appear in the debug toolbar, plus the status bar of the IDE, after the 1st run:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237982-debuganything-06-04-name.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237982-debuganything-06-04-name.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;url&lt;/code&gt; needs to match the address where our dev version is served (&lt;a href="http://localhost:1234/" rel="noopener noreferrer"&gt;http://localhost:1234/&lt;/a&gt; by default).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;webRoot&lt;/code&gt;: the filesystem path that matches the root of the dev server. It is usually the folder where the entry point is kept - in our case the folder where &lt;code&gt;index.html&lt;/code&gt; is. Keep in mind that the example code repo houses multiple small projects. In a single-project repo, &lt;code&gt;"webRoot": "${workspaceFolder}/src"&lt;/code&gt; is a good first guess.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pathMapping&lt;/code&gt;: this option is required in our case, as Parcel serves up a source-map that makes it look like the original files are under &lt;code&gt;/__parcel_source_root&lt;/code&gt;. Without this setting VS Code would be unable to map breakpoint locations in the source to runtime code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237889-debuganything-06-05-breakpoint-bound.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237889-debuganything-06-05-breakpoint-bound.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Check your &lt;code&gt;pathMapping&lt;/code&gt; if you encounter "Breakpoint set but not yet bound" issues&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can find the correct path in the debug browser by the way. In Chrome, open the dev console and go to Sources:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237892-debuganything-06-06-find-map-name.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237892-debuganything-06-06-find-map-name.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we set &lt;code&gt;skipFiles&lt;/code&gt; so that the debugger never &lt;a href="https://charlesagile.com/debug-javascript-typescript-debugger-navigating-with-steps" rel="noopener noreferrer"&gt;steps into&lt;/a&gt; 3rd party or core Node.js modules. Skipping such files is useful if you want to focus on your codebase and are not interested in spending time looking at library code—a highly recommended tweak.&lt;/p&gt;

&lt;h1&gt;
  
  
  React + TypeScript debugger in action
&lt;/h1&gt;

&lt;p&gt;Make sure the dev server is running, then launch the debug browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237896-debuganything-06-07-start.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237896-debuganything-06-07-start.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add two breakpoints: one inside the &lt;code&gt;fetchBody&lt;/code&gt; function, another into the &lt;code&gt;useEffect&lt;/code&gt; hook:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237903-debuganything-06-08-breakp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237903-debuganything-06-08-breakp.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can restart the debugger (not the server!) and check the hook's behaviour when the component is mounted first:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237908-debuganything-06-09-hook1x2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237908-debuganything-06-09-hook1x2.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we can follow the code flow of &lt;code&gt;fetchBody&lt;/code&gt; - note how we never see any core or 3rd party libraries (like Fetch or React internals):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237921-debuganything-06-10-fetchx2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1588237921-debuganything-06-10-fetchx2.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hopefully, you'll be able to implement a comfortable debug workflow in your React/TypeScript app based on this template ✌️&lt;/p&gt;

&lt;p&gt;Have any tips or comments to share? &lt;a href="https://twitter.com/thekarel" rel="noopener noreferrer"&gt;Let me know&lt;/a&gt;! &lt;/p&gt;

</description>
      <category>debug</category>
      <category>react</category>
      <category>typescript</category>
      <category>parceljs</category>
    </item>
    <item>
      <title>Debug anything: Browser-based React apps</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Mon, 04 May 2020 09:15:45 +0000</pubDate>
      <link>https://dev.to/thekarel/debug-anything-browser-based-react-apps-4imo</link>
      <guid>https://dev.to/thekarel/debug-anything-browser-based-react-apps-4imo</guid>
      <description>&lt;h1&gt;
  
  
  Code setup
&lt;/h1&gt;

&lt;p&gt;To speed things up, I've prepared a simple React app we can play with here, so all you need to do is to check out &lt;a href="https://github.com/thekarel/debug-anything" rel="noopener noreferrer"&gt;the repo for this series&lt;/a&gt; and start the CRA dev server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:thekarel/debug-anything.git
cd debug-anything/react-cra
yarn # npm i
yarn start # npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a successful launch message in your console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Compiled successfully!

You can now view react-cra &lt;span class="k"&gt;in &lt;/span&gt;the browser.

  Local:            http://localhost:3000
  On Your Network:  http://192.168.0.4:3000

Note that the development build is not optimized.
To create a production build, use yarn build.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Creating a &lt;code&gt;launch.json&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;As discussed before, we need a &lt;code&gt;launch.json&lt;/code&gt; for non-trivial use cases - see &lt;a href="https://charlesagile.com/vscode-launch-json-and-the-debug-console" rel="noopener noreferrer"&gt;Debug anything: launch.json &amp;amp; the debug console&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;The sample code already contains the launch configuration too. It's pretty straightforward, but let's walk through it line by line, to make sure we understand what's happening. Open &lt;code&gt;.vscode/launch.json&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457097-deuganything-05-01-launch-json.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457097-deuganything-05-01-launch-json.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's focus on lines 8 to 12 and go from top to bottom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Debug CRA web app in Chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"webRoot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/react-cra"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;type&lt;/code&gt;: this sets the debugger type to &lt;code&gt;chrome&lt;/code&gt;, meaning we'll use Chrome browser in this config. Another type we've before used is &lt;code&gt;node&lt;/code&gt; - there are many others you can get by installing extensions. There's one for &lt;a href="https://marketplace.visualstudio.com/items?itemName=firefox-devtools.vscode-firefox-debug" rel="noopener noreferrer"&gt;Firefox&lt;/a&gt; too 🦊 &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Each debugger &lt;code&gt;type&lt;/code&gt; has its specific configuration, so try to use the handy autocomplete that comes with VS Code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;request&lt;/code&gt;: the selected option &lt;code&gt;launch&lt;/code&gt; means we'll launch a browser for debugging and it will load the address specified below. It's not very different from what you'd do manually, but Code automates it for you. Another possibility is to &lt;code&gt;attach&lt;/code&gt; to an already running debug server, which is not possible here.  It's good to know that VS Code will take care of closing Chrome when you stop the debug session.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;name&lt;/code&gt;: any name you prefer, this will show up in the debug toolbar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457102-deuganything-05-02-name.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457102-deuganything-05-02-name.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;url&lt;/code&gt;: the URL the browser will load - &lt;strong&gt;this has to match the one where the CRA dev server is running!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;code&gt;webRoot&lt;/code&gt;: the path to the project source files. &lt;em&gt;Source maps are not reliable in CRA development mode, unfortunately.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The CRA debug recipe
&lt;/h1&gt;

&lt;p&gt;So how does all this hang together? The debug process is made up of the following steps.&lt;/p&gt;

&lt;p&gt;First,  you start the dev server in a console with &lt;code&gt;npm start&lt;/code&gt; - this can be done in VS Code too by the way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457106-deuganything-05-03-start-script.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457106-deuganything-05-03-start-script.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you &lt;em&gt;launch&lt;/em&gt; the debug browser from the debug sidebar, or by pressing &lt;code&gt;F5&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457110-deuganything-05-04-start-browser.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457110-deuganything-05-04-start-browser.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add breakpoints to your code as usual:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457138-deuganything-05-05-breakpoints.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457138-deuganything-05-05-breakpoints.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then interact with the site in the debug browser, but this time with the debug powers enabled 💪 Let's see how a successful &lt;code&gt;fetch&lt;/code&gt; looks like in our sample app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457143-deuganything-05-06-success-debug.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457143-deuganything-05-06-success-debug.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can restart the session and bring the app back to its original state by using Restart in the toolbar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457163-deuganything-05-07-restart-debug.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457163-deuganything-05-07-restart-debug.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might be wondering if this is any better than opening the page in a "normal" Chrome and using the dev tools? The difference is not huge in this case. One clear benefit, though, is that you get to keep your breakpoints even after you close the browser or quit Code. This applies to watch expressions too! Speaking of which...&lt;/p&gt;

&lt;h1&gt;
  
  
  Bonus: adding watch expressions
&lt;/h1&gt;

&lt;p&gt;We've seen how to &lt;a href="https://charlesagile.com/debug-anything-editing-variables-and-restarting-functions#hello-undefined" rel="noopener noreferrer"&gt;inspect and even edit local variables&lt;/a&gt;. Going to the variables section and looking at values works. But if you're dealing with complex objects, repeatedly opening up nested structures gets annoying fast. &lt;/p&gt;

&lt;p&gt;VS Code offers a more comfortable solution: you can set &lt;em&gt;watch expressions&lt;/em&gt; that will be re-evaluated in each debug step. It's even possible to query nested properties with the dot notation (e.g. &lt;code&gt;post.title&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Make sure the &lt;strong&gt;Watch&lt;/strong&gt; section is open in the debug sidebar and add a few expressions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457180-deuganything-05-08-add-watch-expression.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457180-deuganything-05-08-add-watch-expression.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's try to fetch an existing post and keep an eye on the expressions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457195-deuganything-05-09-watch-200.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457195-deuganything-05-09-watch-200.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With these expressions, it's easy to inspect the unhappy path too - keep an eye on the &lt;code&gt;error&lt;/code&gt; this time:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457222-deuganything-05-09-watch-404.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1587457222-deuganything-05-09-watch-404.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you might have guessed, the method we used above applies to any browser-based app. The setup is roughly the following in these cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start the development server&lt;/li&gt;
&lt;li&gt;Configure your &lt;code&gt;launch.json&lt;/code&gt; to open the app in the debugging browser&lt;/li&gt;
&lt;li&gt;Set breakpoints in your source code&lt;/li&gt;
&lt;li&gt;Set watch expressions when you repeatedly inspect the same property&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://charlesagile.com/debug-javascript-typescript-debugger-navigating-with-steps" rel="noopener noreferrer"&gt;step commands&lt;/a&gt; to inspect the code flow&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://charlesagile.com/debug-anything-editing-variables-and-restarting-functions#rewind" rel="noopener noreferrer"&gt;Restart functions&lt;/a&gt; or the whole app&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>debug</category>
      <category>react</category>
      <category>cra</category>
      <category>learn</category>
    </item>
    <item>
      <title>Debug anything: launch.json &amp; the debug console</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Mon, 27 Apr 2020 20:27:43 +0000</pubDate>
      <link>https://dev.to/thekarel/debug-anything-launch-json-the-debug-console-56i6</link>
      <guid>https://dev.to/thekarel/debug-anything-launch-json-the-debug-console-56i6</guid>
      <description>&lt;p&gt;Debugging can be an intricate business, and we need a way to store the config for our bespoke setup - ports, paths, arguments, and so on - somewhere. VSCode uses &lt;code&gt;launch.json&lt;/code&gt; for fine-grained control and having one will make it possible to start our app or attach to it in complex debug scenarios. Not having a &lt;code&gt;launch.json&lt;/code&gt; was a temporary hack, but we'll need one moving forwards. So let's create one!&lt;/p&gt;

&lt;p&gt;Make sure &lt;a href="https://github.com/thekarel/debug-anything" rel="noopener noreferrer"&gt;our sample code folder&lt;/a&gt; is open in VSCode:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853173-deuganything-04-01-folder-open.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853173-deuganything-04-01-folder-open.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  launch.json
&lt;/h1&gt;

&lt;p&gt;VSCode has a handy UI to generate a config skeleton. Let's switch to the debug sidebar, click "create a launch.json file" and select Node.js:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853110-deuganything-04-02-generate-launch-json.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853110-deuganything-04-02-generate-launch-json.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VSCode generates a new &lt;code&gt;launch.json&lt;/code&gt; file under the &lt;code&gt;.vscode&lt;/code&gt; folder in the workspace:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853125-deuganything-04-03-show-launchjson.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853125-deuganything-04-03-show-launchjson.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll dig deeper into the file format and possible values in the future when we'll look at different real-life scenarios and adapt the configuration as required.&lt;/p&gt;

&lt;p&gt;For now, it's enough to observe that the presence of the config enables a launch menu in the debug sidebar which you can use to start the toy server 🧸 quickly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853129-deuganything-04-04-running-debug.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853129-deuganything-04-04-running-debug.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can refer to the excellent official documentation on &lt;a href="https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations" rel="noopener noreferrer"&gt;creating the configuration&lt;/a&gt; and &lt;a href="https://code.visualstudio.com/Docs/editor/debugging#_launchjson-attributes" rel="noopener noreferrer"&gt;the possible configuration values&lt;/a&gt; if you'd like to understand more about this topic right now.&lt;/p&gt;

&lt;p&gt;By the way, I'd suggest saving &lt;code&gt;launch.json&lt;/code&gt; to your code repo. Having a shared one enables all team members to take advantage of proper debugging.&lt;/p&gt;

&lt;h1&gt;
  
  
  Debug Console
&lt;/h1&gt;

&lt;p&gt;Note how the debug console also opened up automatically:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853150-deuganything-04-05-debug-console-open.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853150-deuganything-04-05-debug-console-open.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This console allows you to evaluate expressions in the context of the app running in the debugger. It is a pretty amazing and convenient tool! You can inspect any variable in the scope, similar to the &lt;a href="https://charlesagile.com/debug-anything-editing-variables-and-restarting-functions#hello-undefined" rel="noopener noreferrer"&gt;debug sidebar&lt;/a&gt;. But you can also run any function in scope, or literally run any code you want, even &lt;code&gt;require&lt;/code&gt; modules - inside your running app 🤯&lt;/p&gt;

&lt;p&gt;Let's see an example. Make sure to &lt;a href="https://charlesagile.com/debug-series-nodejs-browser-javascript#start-the-debugger" rel="noopener noreferrer"&gt;add a breakpoint&lt;/a&gt; on line 24 and fire off a request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853154-deuganything-04-06-use-debug-console.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853154-deuganything-04-06-use-debug-console.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As demonstrated, you can type in any local variable (or function) name, and you even get auto-completion.&lt;/p&gt;

&lt;p&gt;But, as mentioned above, you're not limited to your app's code -  you can import any available module:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853106-deuganything-04-07-require-console.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586853106-deuganything-04-07-require-console.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have fun exploring the debug console! 🥼&lt;/p&gt;

</description>
      <category>debug</category>
      <category>vscode</category>
      <category>node</category>
      <category>learn</category>
    </item>
    <item>
      <title>Debug anything: Editing variables and restarting functions</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Mon, 20 Apr 2020 07:14:11 +0000</pubDate>
      <link>https://dev.to/thekarel/debug-anything-editing-variables-and-restarting-functions-4e2</link>
      <guid>https://dev.to/thekarel/debug-anything-editing-variables-and-restarting-functions-4e2</guid>
      <description>&lt;p&gt;Previously we've looked at how to &lt;a href="https://charlesagile.com/debug-series-nodejs-browser-javascript" rel="noopener noreferrer"&gt;start debugging a simple server&lt;/a&gt; and the ways you can &lt;a href="https://charlesagile.com/debug-javascript-typescript-debugger-navigating-with-steps" rel="noopener noreferrer"&gt;move around the code&lt;/a&gt; in the debugger. Today we'll check out two less prominent features. The first one is the ability to edit variables. The second being the ability to replay a function - to restart a &lt;a href="https://en.wikipedia.org/wiki/Call_stack#Structure" rel="noopener noreferrer"&gt;stack frame, to be precise&lt;/a&gt; - without restarting the debugger or the application.&lt;/p&gt;

&lt;p&gt;While these features might not be super intuitive, they are quite powerful and can save a ton of time. You can try a function buried deep in the call stack with different inputs, without restarting a potentially long and tedious journey.&lt;/p&gt;

&lt;p&gt;Let's see how we can use them together to try different scenarios in our usual &lt;a href="https://github.com/thekarel/debug-anything/blob/master/node/index.js" rel="noopener noreferrer"&gt;tiny server app&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;We'll play around with the usual code snippet, go ahead and copy-paste it into an empty file if it's not on your machine yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3456&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNameFromReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getGreeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNameFromReq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getGreeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563843-deuganything-02-01-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563843-deuganything-02-01-code.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Hello, undefined!
&lt;/h1&gt;

&lt;p&gt;Our toy server assumes there is always a query parameter called &lt;code&gt;name&lt;/code&gt; present in the request. If it's missing, the response becomes "Hello, undefined!":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; curl http://127.0.0.1:3456
Hello, undefined!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's use the debugger and see how our &lt;code&gt;getGreeting&lt;/code&gt; function behaves with different &lt;code&gt;name&lt;/code&gt; parameters. The fix is trivial, obviously, but let's play along, we're here to see what the debugger can do. 🤓&lt;/p&gt;

&lt;p&gt;Let's put a breakpoint on line 15 and hit the server without a name query argument (e.g. &lt;code&gt;curl http://127.0.0.1:3456&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;You should see the debugger kicking in and stopping on line 15. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334485-deuganything-03-01-stop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334485-deuganything-03-01-stop.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you're not confident how to do this, please refer to &lt;a href="https://charlesagile.com/debug-series-nodejs-browser-javascript" rel="noopener noreferrer"&gt;Part 1, the basics&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Make sure the Variables and Call stack sections are both open in the debug sidebar. We'll focus on the local variable &lt;code&gt;name&lt;/code&gt; for now, which is undefined:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334491-deuganything-03-02-undefined.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334491-deuganything-03-02-undefined.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's step over the next line (&lt;code&gt;F10&lt;/code&gt;) and observe the return value of &lt;code&gt;getGreeting&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334496-deuganything-03-03-returnvalue.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334496-deuganything-03-03-returnvalue.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you need a quick overview of step over, step into and step out, read &lt;a href="https://charlesagile.com/debug-javascript-typescript-debugger-navigating-with-steps" rel="noopener noreferrer"&gt;Part 2, Navigating with steps&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ok, no surprises here: if the &lt;code&gt;name&lt;/code&gt; is &lt;code&gt;undefined&lt;/code&gt;, the greeting will say &lt;code&gt;Hello, undefined!&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Rewind
&lt;/h1&gt;

&lt;p&gt;Let's re-run this function, this time with a different &lt;code&gt;name&lt;/code&gt;. We don't need to fire off another request - we can restart the last stack frame:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334507-deuganything-03-04-restart.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334507-deuganything-03-04-restart.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we're back at the beginning of the &lt;code&gt;getGreeting&lt;/code&gt; function 👌&lt;/p&gt;

&lt;p&gt;Let's now try what would happen if the name was &lt;code&gt;null&lt;/code&gt;? We can edit the local variable to fund out:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334522-deuganything-03-05-null.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334522-deuganything-03-05-null.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can try to set a string value - mind the quotes around the value:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334543-deuganything-03-06-string-override.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334543-deuganything-03-06-string-override.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can override anything local or defined in the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" rel="noopener noreferrer"&gt;closure&lt;/a&gt;, including functions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334558-deuganything-03-07-redefine-func.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1586334558-deuganything-03-07-redefine-func.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Keep in mind: once you override functions you'll have to restart the process to get back to the original implementation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And this is it: you are now able to restart functions in the debugger and edit local and closure values, including strings and functions. Why not play around and see what happens if you restart functions higher up in the stack?&lt;/p&gt;

&lt;p&gt;Happy debugging! 🥼&lt;/p&gt;

</description>
      <category>debug</category>
      <category>vscode</category>
      <category>node</category>
      <category>learn</category>
    </item>
    <item>
      <title>Debug Anything: Navigating with steps</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Tue, 14 Apr 2020 05:28:29 +0000</pubDate>
      <link>https://dev.to/thekarel/debug-anything-navigating-with-steps-3c8g</link>
      <guid>https://dev.to/thekarel/debug-anything-navigating-with-steps-3c8g</guid>
      <description>&lt;p&gt;In the &lt;a href="https://charlesagile.com/debug-series-nodejs-browser-javascript" rel="noopener noreferrer"&gt;previous episode&lt;/a&gt; we've started exploring the VS Code debugger. We've added breakpoints to our tiny codebase and glanced at the local state. &lt;/p&gt;

&lt;p&gt;This time we'll learn how to follow the code execution line by line and how to jump in and out of function calls.&lt;/p&gt;

&lt;h1&gt;
  
  
  Get the code
&lt;/h1&gt;

&lt;p&gt;First, let's change our single-function server into something more complex. We'll add two extra functions: one to get the name from the request and another to generate the greeting.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can copy-paste this code as &lt;code&gt;index.js&lt;/code&gt; in an empty folder.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3456&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNameFromReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getGreeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getNameFromReq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getGreeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563843-deuganything-02-01-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563843-deuganything-02-01-code.png" alt="Source code opened in VS Code" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The code for the series is available at &lt;a href="https://github.com/thekarel/debug-anything" rel="noopener noreferrer"&gt;https://github.com/thekarel/debug-anything&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Start the debugger
&lt;/h1&gt;

&lt;p&gt;Let's start the debugger: &lt;a href="https://charlesagile.com/debug-series-nodejs-browser-javascript#start-the-debugger" rel="noopener noreferrer"&gt;use the debug toolbar&lt;/a&gt; or press &lt;code&gt;F5&lt;/code&gt; and select &lt;code&gt;Node.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563896-deuganything-02-02-start.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563896-deuganything-02-02-start.gif" alt="Starting the debugger" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should be able to visit &lt;a href="http://127.0.0.1:3456/?name=Coco" rel="noopener noreferrer"&gt;http://127.0.0.1:3456/?name=Coco&lt;/a&gt; as usual and see a greeting. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can also use &lt;code&gt;curl http://127.0.0.1:3456\?name\=Coco&lt;/code&gt; if you're that kind of person&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok, so far we've only established the server is up and running - let's add a breakpoint. Without a breakpoint, the debugger wouldn't start:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563890-deuganything-02-03-bp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563890-deuganything-02-03-bp.gif" alt="Adding a breakpoint" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should have a breakpoint now on line 21:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const name = getNameFromReq(req)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Step by Step
&lt;/h1&gt;

&lt;p&gt;Fire off a request again to &lt;a href="http://127.0.0.1:3456/?name=Coco" rel="noopener noreferrer"&gt;http://127.0.0.1:3456/?name=Coco&lt;/a&gt; - the debugger will kick in and stop code execution on line 21:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563885-deuganything-02-04.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563885-deuganything-02-04.png" alt="Debugger started" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wonderful. Let's focus on the &lt;em&gt;debug toolbar now&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563880-deuganything-02-05-bar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563880-deuganything-02-05-bar.png" alt="The debugger toolbar" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First of all: names. The buttons from left to right are the following (with the default VS Code shortcut):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continue / Pause &lt;code&gt;F5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Step Over &lt;code&gt;F10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Step Into &lt;code&gt;F11&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Step Out &lt;code&gt;⇧F11&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Restart &lt;code&gt;⇧⌘F5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Stop &lt;code&gt;⇧F5&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Continue, restart and stop are straightforward and will do what you expect: continue to the next breakpoint, restart the process and stop the process (and the debugger).&lt;/p&gt;

&lt;p&gt;Steps are related to function calls on the current line: you can step over a function call, step into it (look inside and debug) or leave it (step out). Step-over also allows you to run the code line by line, even if the line is not a function call. &lt;/p&gt;

&lt;p&gt;Step commands only control what you "see" in the debugger. So "stepping out" or "over" a function will &lt;em&gt;still execute all the code as usual&lt;/em&gt;.  The debugger will just not bore you with the details, and you'll get jor job done quicker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continue
&lt;/h2&gt;

&lt;p&gt;Continue will run the code up to the next breakpoint, or the end of the program. One way of debugging is to add multiple breakpoints on relevant  lines beforehand and jump between them using continue:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563865-deuganything-02-06-continue.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563865-deuganything-02-06-continue.gif" alt="Using continue to jump to the next breakpoint" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, Continue is handy if you already know which functions or lines are relevant to you. The debugger will pause at pre-defined locations allowing you to inspect the variables and call stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step Over
&lt;/h2&gt;

&lt;p&gt;You can think of step over as going line-by-line in a function but not following function calls (not stepping in). Use it if you're not interested in the details of the function call on the current line, but only want to see how local variables change over time, for example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563848-deuganything-02-07-step-over.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585563848-deuganything-02-07-step-over.gif" alt="Using step over" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step over is a great way to walk trough &lt;a href="https://charlesagile.com/declarative-programming-writing-correct-and-easy-to-understand-code" rel="noopener noreferrer"&gt;devlarative code&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step Into
&lt;/h2&gt;

&lt;p&gt;You can use step-into when you arrive on a line that calls an interesting function, and you want to dig deeper. Once you step into a block, you keep debugging as usual (use continue, step commands, etc.).&lt;/p&gt;

&lt;p&gt;Observe how we step over &lt;code&gt;getNameFromReq&lt;/code&gt; but &lt;em&gt;step into&lt;/em&gt; &lt;code&gt;getGreeting&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585636717-deuganything-02-08-step-into.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585636717-deuganything-02-08-step-into.gif" alt="Using step into" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step Out
&lt;/h2&gt;

&lt;p&gt;Stepping out is the opposite of stepping in: you can leave a function once you're no longer interested in it. Clicking "Step out" runs the remaining code of the function without you having to keep clicking. &lt;/p&gt;

&lt;p&gt;Check out the difference between debugging the two functions - we follow the first one through but step out of the second early:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585636693-deuganything-02-09-step-out.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585636693-deuganything-02-09-step-out.gif" alt="Using step out" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you should have a better understanding of the debugger toolbar, how to &lt;a href="https://charlesagile.com/paying-attention-the-mental-cost-of-development" rel="noopener noreferrer"&gt;focus on what matters&lt;/a&gt; and skip the irrelevant bits. The navigation commands not only save you time but make the whole debugging activity more enjoyable! Why not try these in your project as an exercise?&lt;/p&gt;

&lt;p&gt;Happy debugging! 🥼&lt;/p&gt;

</description>
      <category>debug</category>
      <category>vscode</category>
      <category>node</category>
      <category>learn</category>
    </item>
    <item>
      <title>Debug anything: the basics (with GIFs!)</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Tue, 07 Apr 2020 05:22:19 +0000</pubDate>
      <link>https://dev.to/thekarel/debug-anything-the-basics-with-gifs-52pb</link>
      <guid>https://dev.to/thekarel/debug-anything-the-basics-with-gifs-52pb</guid>
      <description>&lt;p&gt;A debugger allows you to open up your program while it runs, look at the state, variables, pause and observe the data flow step by step. You can even run code snippets and try ideas in the runtime environment. All that without stopping, changing code (adding console.log!) and restarting. You'll fix issues and understand the codebase much faster with a debugger.&lt;/p&gt;

&lt;p&gt;We'll start with some suspiciously simple Node.js code, and in the future will look at debugging a browser app, Express server, GraphQL, TypeScript, Serverless, Jest tests, Storybook - but let's clear the basics first! Even if you're not keen on server-side Node.js, I'd still encourage you to go over this introduction.&lt;/p&gt;

&lt;h1&gt;
  
  
  Get the code
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Git repo for the series: &lt;a href="https://github.com/thekarel/debug-anything" rel="noopener noreferrer"&gt;https://github.com/thekarel/debug-anything&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code for our first session is super simple - go ahead and copy-paste it to &lt;code&gt;index.js&lt;/code&gt; in an empty folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3456&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now go ahead and open the folder in VS Code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215553-deuganything-01-00-node-code-open.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215553-deuganything-01-00-node-code-open.png" alt="Open the code" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make sure all is well so far, try to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... and visit &lt;a href="http://127.0.0.1:3456" rel="noopener noreferrer"&gt;http://127.0.0.1:3456&lt;/a&gt; - you should see &lt;code&gt;Hello, World!&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Make sure you stop the &lt;code&gt;node index.js&lt;/code&gt; command now, or you'll get an ugly &lt;code&gt;Error: listen EADDRINUSE&lt;/code&gt; error soon 🙀&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The code itself is trivial: we run an HTTP server, and respond to every request with "Hello, World!". Impressive, right? But this simple code is enough to learn the basic notions of debugging. &lt;/p&gt;

&lt;h1&gt;
  
  
  Add a new feature
&lt;/h1&gt;

&lt;p&gt;Let's add a feature to our server: instead of returning the hard-coded message "Hello, World!", we'll pick the &lt;code&gt;name&lt;/code&gt; from the query, so hitting &lt;a href="http://127.0.0.1:3456?name=Coco" rel="noopener noreferrer"&gt;http://127.0.0.1:3456?name=Coco&lt;/a&gt; will respond with &lt;code&gt;Hello, Coco!&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Also, let's pretend we have no idea how to do it ;) Wouldn't it be nice to be able to run the server, send a request and see where the name &lt;code&gt;Coco&lt;/code&gt; shows up? Let's give it a try. Let's start the debugger!&lt;/p&gt;

&lt;h1&gt;
  
  
  Start the debugger
&lt;/h1&gt;

&lt;p&gt;Make sure &lt;code&gt;index.js&lt;/code&gt; is open in VS Code, click the debugger icon, click Run and Debug then Node.js:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215624-deuganything-01-01-node-basic-launch.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215624-deuganything-01-01-node-basic-launch.gif" alt="Start the debugger" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your server is now running in debug mode! Try visiting &lt;a href="http://127.0.0.1:3456?name=Coco" rel="noopener noreferrer"&gt;http://127.0.0.1:3456?name=Coco&lt;/a&gt; - you won't see a difference, but it should still return the default message.&lt;/p&gt;

&lt;p&gt;Next, let's add a &lt;em&gt;breakpoint&lt;/em&gt; to the code which will pause the execution the next time we hit the server URL. You can do that by clicking the line number in the left gutter of the editor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215606-deuganything-01-02-node-basic-add-breakpoint.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215606-deuganything-01-02-node-basic-add-breakpoint.gif" alt="Adding a breakpoint" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try visiting &lt;a href="http://127.0.0.1:3456?name=Coco" rel="noopener noreferrer"&gt;http://127.0.0.1:3456?name=Coco&lt;/a&gt; - VS Code will pop into view and pause the server:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215602-deuganything-01-03-breaking.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215602-deuganything-01-03-breaking.png" alt="Breakpoint in action" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's find out where the name in the query ends up, so we can return a friendly greeting. Check out the &lt;em&gt;left sidebar&lt;/em&gt;: you'll see a section named &lt;em&gt;Variables&lt;/em&gt;. Under &lt;em&gt;Local&lt;/em&gt; the IDE shows all the vars that are in the local scope of the function. There's one that looks promising: &lt;code&gt;req&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215585-deuganything-01-04-node-open-req.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215585-deuganything-01-04-node-open-req.gif" alt="Inspecting req" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know that the request query string sits in &lt;code&gt;req.url&lt;/code&gt;, &lt;a href="https://nodejs.org/en/knowledge/HTTP/clients/how-to-access-query-string-parameters/" rel="noopener noreferrer"&gt;with a little help&lt;/a&gt; we can go ahead and change the script to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 👈&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;127.0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3456&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// 👈&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the code changed, you need to restart the server. It's simple to do with the debugger: you can press &lt;code&gt;⇧⌘F5&lt;/code&gt; or click the green restart icon:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215570-deuganything-01-05-node-restart.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215570-deuganything-01-05-node-restart.gif" alt="Restart the server" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also disable the breakpoint as we don't need it anymore:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215564-deuganything-01-06-disable-breakpoint.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.datocms-assets.com%2F22772%2F1585215564-deuganything-01-06-disable-breakpoint.gif" alt="Disable the breakpoint" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Visit &lt;a href="http://127.0.0.1:3456?name=Coco" rel="noopener noreferrer"&gt;http://127.0.0.1:3456?name=Coco&lt;/a&gt; and marvel at how much one can achieve with today's technology! 😉&lt;/p&gt;

&lt;p&gt;I encourage you to keep exploring the debugger. Next time we'll look at walking through the code line by line using the "step over", "step in" and "step out" functionality.&lt;/p&gt;

&lt;p&gt;Happy debugging! 🥼&lt;/p&gt;

</description>
      <category>debug</category>
      <category>vscode</category>
      <category>node</category>
      <category>learn</category>
    </item>
    <item>
      <title>Declarative programming: correct and easy to understand code</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Mon, 30 Mar 2020 06:20:55 +0000</pubDate>
      <link>https://dev.to/thekarel/declarative-programming-correct-and-easy-to-understand-code-1jl5</link>
      <guid>https://dev.to/thekarel/declarative-programming-correct-and-easy-to-understand-code-1jl5</guid>
      <description>&lt;p&gt;&lt;em&gt;This article is part of &lt;a href="https://thekarel.gitbook.io/best-practices/" rel="noopener noreferrer"&gt;Best Practices - Pragmatic recommendations based on clean coding principles for teams working on TypeScript/JavaScript web application&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Maintainable code is &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/principles/simple" rel="noopener noreferrer"&gt;simple&lt;/a&gt;, &lt;a href="https://thekarel.gitbook.io/best-practices/source-code/folderstructure" rel="noopener noreferrer"&gt;discoverable&lt;/a&gt; and easy to understand.&lt;/p&gt;

&lt;p&gt;How do we write code that others understand easily? By stating our intentions in short, abstract, human language-like expressions and moving the technical details into lower-level modules.&lt;/p&gt;

&lt;p&gt;Consider the following code snippet. It is obvious what's supposed to happen without seeing the implementation details, and it's also clear where to look to understand more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buyTicket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;concertId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConcertId&lt;/span&gt;&lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Ticket&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;concert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getConcert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;concertId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;ticketsAvailableFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;concert&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TicketsNotAvailableError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;hasFundsFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;concert&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NotEnoughFundsError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ticket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Ticket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;concert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recordTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ticket&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code more or less reads like a recipe in English: get the user and the concert, check if tickets and the money are available - if so, deduct the money and hand over a ticket.&lt;/p&gt;

&lt;p&gt;Production code would be more complicated than this example, but the pattern is quite clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State your intentions in expressive, human-friendly language&lt;/li&gt;
&lt;li&gt;Stay on one level of abstraction inside &lt;a href="https://thekarel.gitbook.io/best-practices/source-code/modules" rel="noopener noreferrer"&gt;a module&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Start from high-level, &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/architecture" rel="noopener noreferrer"&gt;domain&lt;/a&gt; language and move to low-level, implementation-specific details&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing declarative code creates building blocks, starting from the top and drilling down to the bottom. You state the most significant, most abstract problem first, then break it down to smaller bits - next go and break down these again and again. At some point down this road, you find ready-made solutions, your existing, reusable code or 3rd party modules.&lt;/p&gt;

&lt;p&gt;You can think of declarative programming as writing a specification first (top-level function calls), then implementing these features one by one. It's easy to imagine that the snippet above started as a list of requirements to implement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buyTicket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// get user&lt;/span&gt;
    &lt;span class="c1"&gt;// get concert&lt;/span&gt;

    &lt;span class="c1"&gt;// check if tickets are still available&lt;/span&gt;
    &lt;span class="c1"&gt;// check if the user has funds&lt;/span&gt;

    &lt;span class="c1"&gt;// create a Ticket&lt;/span&gt;
    &lt;span class="c1"&gt;// create sale transaction&lt;/span&gt;

    &lt;span class="c1"&gt;//return ticket&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While details in a declarative codebase are not immediately visible, they are still easily accessible. When you need to understand specifics, you should be able to "jump to definition" in your IDE - or open the relevant file, which is straightforward with &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/naming" rel="noopener noreferrer"&gt;consistent naming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The definition of the lower-level code block must also follow the declarative principles - so it's also easy to understand. This pattern repeats like a fractal, from top to bottom, from very abstract to the lowest level.&lt;/p&gt;

&lt;p&gt;One function (method) must deal with one level of abstraction. Sticking to the rule of increasing specificity makes reading and changing the program straightforward, as readers don't have to jump between contexts, which is very distracting and drains &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/principles/attention" rel="noopener noreferrer"&gt;attention&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Declarative code builds up complex structures from smaller building blocks. In this regard, it's very similar to the compositional nature of functional programming. But using FP is not a requirement; you can use this technique in object-oriented programming or any other/mixed paradigm.&lt;/p&gt;

&lt;p&gt;The main goal here is to write something easy to understand for others - and ourselves in the future. But declarative programming has other benefits too: refactoring is more manageable because you've extracted implementation details, so changing "how" we do something doesn't affect the "what". Also, finding the code responsible for a piece of functionality is almost trivial. You might have to go through several modules (more indirection), but the path to follow is always evident. You might have to walk a bit more, but you're guaranteed to get there - and this is key in a product-oriented environment.&lt;/p&gt;

&lt;p&gt;The expressive strategy described here works well outside of programming too. You are encouraged to be declarative when recording requirements, writing documentation, describing systems, creating tests, scripts, CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;Finally, consider how the opposite of declarative code looks like: everything stares at you at once, from technical details to high-level concepts, from counters and indexes to business entities, all mixed. Such source code is confusing and difficult to follow - and precisely because of that becomes a breeding ground for bugs.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>declarative</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>The only problem to solve is the one we have today</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Thu, 26 Mar 2020 10:41:51 +0000</pubDate>
      <link>https://dev.to/thekarel/the-only-problem-to-solve-is-the-one-we-have-today-1dd3</link>
      <guid>https://dev.to/thekarel/the-only-problem-to-solve-is-the-one-we-have-today-1dd3</guid>
      <description>&lt;p&gt;What you need to solve are the problems you have &lt;em&gt;now&lt;/em&gt;: dedicate &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/principles/attention" rel="noopener noreferrer"&gt;proper focus&lt;/a&gt; to these. Produce a correct solution for the task at hand and move on. &lt;/p&gt;

&lt;p&gt;Worrying about what might happen in an imaginary scenario leads you down into rabbit holes. It is one of the reasons why people start many things but finish few.&lt;/p&gt;

&lt;p&gt;Another reason to refrain from "preemptive" solutions is the lack of information. You will know more about the problem domain later and will be able to come up with a better solution "just in time".&lt;/p&gt;

&lt;p&gt;Finally, you limit your future choices by making sub-optimal decisions now. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't paint yourself into a corner by making uninformed judgments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you keep your application &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/principles/simple" rel="noopener noreferrer"&gt;as simple as possible&lt;/a&gt;, you'll have a much higher chance to adapt to future changes successfully. &lt;/p&gt;

&lt;p&gt;You can't predict the future, and surprises will happen. What you have planned might never arrive, something completely different probably will. &lt;/p&gt;

&lt;p&gt;Continue reading &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/principles/today" rel="noopener noreferrer"&gt;The only problem to solve is the one we have today&lt;/a&gt; in &lt;a href="https://thekarel.gitbook.io/best-practices/" rel="noopener noreferrer"&gt;Best Practices&lt;/a&gt;&lt;/p&gt;

</description>
      <category>focus</category>
      <category>productivity</category>
      <category>principle</category>
      <category>optimiziation</category>
    </item>
    <item>
      <title>Simplicity is a developer's best friend</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Mon, 16 Mar 2020 09:36:57 +0000</pubDate>
      <link>https://dev.to/thekarel/simplicity-is-a-developer-s-best-friend-58b8</link>
      <guid>https://dev.to/thekarel/simplicity-is-a-developer-s-best-friend-58b8</guid>
      <description>&lt;p&gt;You need to embrace simplicity if you want to achieve results today and stay successful tomorrow. Long term product quality, performance and development speed all rest on the simplicity of a system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Run with the minimum that achieves the business goals.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are two kinds of complexity in any project: the inherent complications of the problem domain and the unnecessary, "incidental" or "accidental" complexity introduced by developers. The domain complexity is more or less fixed and has to be accepted as is. Dealing with it is the primary role of a developer.&lt;br&gt;
Accidental complexity, on the other hand, has to be avoided and minimised at all cost.&lt;/p&gt;

&lt;p&gt;Be frugal with code, processes and infrastructure. Everything you add today will have to be looked at and understood by you or someone else in the future. The more complicated your system is, the more resources people dedicate to learning it instead of implementing improvements and new features.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Simple might seem boring at first - but it's the opposite: it's liberating. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Continue reading &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/principles/simple" rel="noopener noreferrer"&gt;Simplicity is the best ally in the long run&lt;/a&gt; on my &lt;a href="https://thekarel.gitbook.io/best-practices/" rel="noopener noreferrer"&gt;Best Practices on GitBook&lt;/a&gt;&lt;/p&gt;

</description>
      <category>simplicity</category>
      <category>delivery</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Paying attention: the mental cost of development</title>
      <dc:creator>Charles Szilagyi</dc:creator>
      <pubDate>Mon, 09 Mar 2020 06:24:22 +0000</pubDate>
      <link>https://dev.to/thekarel/paying-attention-the-mental-cost-of-development-2ojn</link>
      <guid>https://dev.to/thekarel/paying-attention-the-mental-cost-of-development-2ojn</guid>
      <description>&lt;p&gt;Writing software requires long periods of uninterrupted concentration. Developers need to consider complex ideas in detail, imagine and experiment with various solutions to discover the one that works. Finding answers often requires research and learning about new concepts. All this is impossible without paying attention.&lt;/p&gt;

&lt;p&gt;For this reason, attention is &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/principles/attention" rel="noopener noreferrer"&gt;the most precious&lt;/a&gt; resource in a software project. Once depleted, no amount of determination, money or time will deliver the desired outcomes. Without focus, all other resources go to waste. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is no such thing as multitasking. You can do one thing well or many things wrong in parallel.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But, attention is also a very fragile thing. Successful developers work in attention-friendly environments without external interruptions. They also learn how to manage and direct their focus on what's relevant: they are disciplined. &lt;/p&gt;

&lt;p&gt;A significant source of distraction is often the codebase and the tooling itself. Teams need to avoid unnecessary complexities in the code and all unproductive practices while writing it. There are some &lt;a href="https://thekarel.gitbook.io/best-practices/" rel="noopener noreferrer"&gt;recommendations you can follow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course, there are other things to do in a project than writing code. But all activities must be organized in a way that encourages and supports periods of deep concentration and thinking. Focus and care always manifest in more reliable, performant, refined and more enjoyable products. Your customers will be grateful!&lt;/p&gt;

&lt;p&gt;Building up a focus-friendly climate takes effort and care, but it's an essential requirement to achieve anything substantial.&lt;/p&gt;

&lt;p&gt;You can find out more about the importance of concentration and focus &lt;a href="https://thekarel.gitbook.io/best-practices/the-big-picture/principles/attention" rel="noopener noreferrer"&gt;in my Best Practices on GitBook&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>codequality</category>
      <category>attention</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
