<?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: Ale Sánchez</title>
    <description>The latest articles on DEV Community by Ale Sánchez (@alesanchez).</description>
    <link>https://dev.to/alesanchez</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%2F362223%2F2b9ce0b4-3006-4249-81fa-c3ebdc0741bb.jpeg</url>
      <title>DEV Community: Ale Sánchez</title>
      <link>https://dev.to/alesanchez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alesanchez"/>
    <language>en</language>
    <item>
      <title>In a stupid defence of human-crafted content</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Thu, 04 Sep 2025 18:57:07 +0000</pubDate>
      <link>https://dev.to/alesanchez/in-a-stupid-defence-of-human-crafted-content-3foa</link>
      <guid>https://dev.to/alesanchez/in-a-stupid-defence-of-human-crafted-content-3foa</guid>
      <description>&lt;p&gt;Recently, I stumbled upon this image from &lt;a href="https://marketoonist.com/2023/03/ai-written-ai-read.html?ref=blog.alesanchez.es" rel="noopener noreferrer"&gt;Marketoonist&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5ltpvcw4blnh4azmmob.webp" 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%2Fuploads%2Farticles%2Fg5ltpvcw4blnh4azmmob.webp" alt="AI Written, AI Read" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And it hit me differently. I came to the realisation that we should defend human-crafted content, even though it may feel stupid.&lt;/p&gt;

&lt;p&gt;So, from now on, I'll try to write concise, to-the-point posts as part of my (rather futile) battle against AI slop.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>developer</category>
      <category>discuss</category>
      <category>contentwriting</category>
    </item>
    <item>
      <title>Presenting Assistant Language. A programming language created with GPT3</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Sun, 04 Dec 2022 14:23:31 +0000</pubDate>
      <link>https://dev.to/alesanchez/presenting-assistant-language-a-programming-language-created-with-gpt3-4b52</link>
      <guid>https://dev.to/alesanchez/presenting-assistant-language-a-programming-language-created-with-gpt3-4b52</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g_WDVVqU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1548614229-c1fe21dfab63%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDE3fHxhcnRpZmljaWFsJTIwaW50ZWxsaWdlbmNlfGVufDB8fHx8MTY3MDE2MzU3Mw%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g_WDVVqU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1548614229-c1fe21dfab63%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDE3fHxhcnRpZmljaWFsJTIwaW50ZWxsaWdlbmNlfGVufDB8fHx8MTY3MDE2MzU3Mw%26ixlib%3Drb-4.0.3%26q%3D80%26w%3D2000" alt="Presenting Assistant Language. A programming language created with GPT3" width="880" height="1100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, so you probably heard about&lt;a href="https://openai.com/blog/chatgpt/"&gt;OpenAI's chatbot&lt;/a&gt;. It's the most advanced chatbot created so far. It can help people with &lt;a href="https://twitter.com/jdjkelly/status/1598021488795586561?s=20&amp;amp;t=t8nTl7LL4F2QE3PqwhmcHQ"&gt;LaTeX questions&lt;/a&gt;, &lt;a href="https://twitter.com/amasad/status/1598042665375105024?s=20&amp;amp;t=REj8r9rcvgo10DFJiyg5fw"&gt;find bugs in code&lt;/a&gt; or solve &lt;a href="https://twitter.com/yieldthought/status/1598238411097530368?s=20&amp;amp;t=36zU8sBI3cc4bJRwLPfXLA"&gt;code challenges&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What I tried for this post is something different. I instructed ChatGPT to create a programming language for me and become the interpreter for that programming language.&lt;/p&gt;

&lt;p&gt;I took the idea and a few useful instructions from &lt;a href="https://www.engraved.blog/building-a-virtual-machine-inside/"&gt;this blog post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's start simple
&lt;/h2&gt;

&lt;p&gt;I started instructing the bot to create a simple language with an instruction to print. Also, it has to act as the interpreter of that language. To keep communicating with the bot I added a special format with slashes and quotes. Here's the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LzqR9Ksd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LzqR9Ksd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-1.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="766" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pb_Mbqr4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pb_Mbqr4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-2.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="744" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to use my prompt, here it is&lt;/p&gt;

&lt;p&gt;I want you to create a new programming language. It has to provide only an instruction for printing something to screen. I want you to explain to me how to use it in a concise way. After that, you will become an interpreter of that language. Answer with the execution result inside one unique code block, and nothing else. Only write explanations if the code contains errors. When I need to tell you something in English, I will put text inside forward slashes and double quotes /"like this"/.&lt;/p&gt;

&lt;p&gt;Ok, looks good so far. Let's try the interpreter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dLC6iLdL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dLC6iLdL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-3.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="843" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks like it worked!&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding functionality to the programming language
&lt;/h2&gt;

&lt;p&gt;Let's try to add some more functionality to our new programming language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Variables
&lt;/h3&gt;

&lt;p&gt;Ok, using the slashes and quotes format I'll try to add variables to the programming language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VC-ajYON--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VC-ajYON--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-4.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="792" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GMDpxD0E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GMDpxD0E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-5.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="725" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, looks promising, let's try the interpreter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jW7kEapN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jW7kEapN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-6.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="816" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Arithmetic operators
&lt;/h3&gt;

&lt;p&gt;Now, the same thing but with arithmetic operators.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TUGFQCFT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TUGFQCFT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-7.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="880" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WvaQ2-rZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WvaQ2-rZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-8.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="713" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1zEWzueV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1zEWzueV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-9.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="696" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know how to use it, let's try it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--km3iLgYE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--km3iLgYE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-10.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="813" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Logic operators
&lt;/h3&gt;

&lt;p&gt;Now, I'll try to add logic operators to the language, but without instructing first about data types or anything else:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WeZJ_OBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WeZJ_OBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-11.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="769" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6LrrpLum--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6LrrpLum--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-12.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="706" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GLcUnF3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GLcUnF3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-13.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="761" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I haven't talked about conditionals or flow control structures, but it added the ternary operator when asked to include logic operators. It may mean that GPT already "knows" the language, just telling me how to use every piece of it when I ask.&lt;/p&gt;

&lt;p&gt;Let's try these new operators:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qSUM1Aqh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qSUM1Aqh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-14.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="803" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  If statement
&lt;/h2&gt;

&lt;p&gt;I don't want to bias the bot so I won't ask it to add &lt;code&gt;if&lt;/code&gt; structure. Instead, I'll ask for a flow control structure for branching based on condition:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HqmTeybk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HqmTeybk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-15.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="862" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ei5R2aR5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ei5R2aR5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-16.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="698" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--58sKu5LE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--58sKu5LE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-17.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="688" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well... exactly what I had in mind... Testing time!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IkeXuwup--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IkeXuwup--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-18.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="807" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison operators
&lt;/h3&gt;

&lt;p&gt;I almost forgot about a crucial part of a programming language, the comparison operators!! Let's add them to our language.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iuKtmaqf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iuKtmaqf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-19.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="880" height="635"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k9EVAkAQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k9EVAkAQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-20.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="702" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IazGt3z0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IazGt3z0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-21.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="747" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RDOwjitG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RDOwjitG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-22.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="751" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, now let's see how it behaves:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kXllHKDx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kXllHKDx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-23.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="808" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Looping
&lt;/h3&gt;

&lt;p&gt;Again, for not biasing the bot, I'll ask for structures to loop or iterate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--om4h5aan--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--om4h5aan--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-24.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="831" height="834"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h9cBcgGR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h9cBcgGR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-25.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="731" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3VGslr0P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3VGslr0P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-26.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="721" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5D5Y2j6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5D5Y2j6s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-27.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="701" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, so it added a classic for loop as well as a while loop...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dwt6pTji--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-28.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dwt6pTji--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-28.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="811" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hmmm... and what if I try to run an infinite loop?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ssFTMmi4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ssFTMmi4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-29.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="859" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It detects it and prevents me from running it!&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions
&lt;/h3&gt;

&lt;p&gt;The next step is to add functions to our new programming language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2c-7Gi4X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2c-7Gi4X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-30.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="880" height="779"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1JtEjr4s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1JtEjr4s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-31.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="787" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wow, we also can return multiple values and unpack them...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uzgQ8IvC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uzgQ8IvC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-32.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="863" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Utility functions
&lt;/h3&gt;

&lt;p&gt;Let's see if we can create some "global" utility functions to make our life easier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mFl1dHQp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-33.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mFl1dHQp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-33.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="824" height="681"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hGXSWMJN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-34.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hGXSWMJN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-34.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="730" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's try to generate some random numbers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CiHKQvIq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CiHKQvIq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-35.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="831" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if we try to add a function to get the current date?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IBqbZ9w6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IBqbZ9w6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-36.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="848" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's do a little test:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1R99Y3Z_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1R99Y3Z_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-37.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="813" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So GPT knows which day it is, but not which time. Interesting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interact with the underlying OS
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C34R-v0l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C34R-v0l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-38.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="826" height="722"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s4Qkv9ov--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-39.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s4Qkv9ov--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-39.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="710" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It already warns me about the &lt;code&gt;shell&lt;/code&gt; function but, of course, I'll try to mess up to see if we can figure out something.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---KXjbTcM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-40.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---KXjbTcM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-40.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="831" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the first time, it included an explanation along with the output, even though there are no errors. Also, the waning message is there again.&lt;/p&gt;

&lt;p&gt;Let's keep testing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vNd4ngp4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vNd4ngp4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-41.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="816" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For some reason, it explains the command instead of executing it. Maybe because it knows that the output won't be the same every time?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I4P61sUj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I4P61sUj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-42.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="792" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did it really create the file? Or is it just "assuming" what would happen...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CNV_-7y_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-43.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CNV_-7y_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-43.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="808" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apparently, it created it... Let's do another test for getting the contents of the root directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--edYptLso--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--edYptLso--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-44.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="845" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hmmm, is the same output as the previous example but with the test dir...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KlmZWoac--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KlmZWoac--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-45.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="804" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nope, it doesn't exist...&lt;/p&gt;

&lt;p&gt;Ok, enough messing with the underlying OS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some advanced features
&lt;/h3&gt;

&lt;p&gt;Would GPT be able to add pointers to our language?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pQnWC0x7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pQnWC0x7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-46.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="836" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T8g2yxEE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T8g2yxEE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-47.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="775" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So... we have pointers now!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FMjm6OPh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FMjm6OPh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-48.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="850" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming the language
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HApcMBBR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HApcMBBR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-49.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="840" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice, I like Assistant Language, let's use it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xncdg69Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xncdg69Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-50.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="853" height="748"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would it be able to implement something in this language?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b7bnKQ9I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b7bnKQ9I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-51.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="817" height="736"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not the most efficient version, but definitely in Assistant Language. Let's test it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y_KB_m4P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y_KB_m4P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-52.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="880" height="681"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It actually works!&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrap it up and provide an interpreter
&lt;/h3&gt;

&lt;p&gt;I want the bot to generate a document with the language specification as well as an interpreter implemented, for example, in Python. Let's try!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QPp8DV5T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-53.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QPp8DV5T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-53.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="789" height="765"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see the full README &lt;a href="https://github.com/alesanmed-blog-posts/assistant-language-gpt3/blob/main/README_generated.md"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And finally... the interpreter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mf2RBEOP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mf2RBEOP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-54.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="880" height="768"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It implemented an interpreter that supports only "let" and "print" statements... Let's see if I can get something more complete.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i-sxx85e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i-sxx85e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/12/image-55.png" alt="Presenting Assistant Language. A programming language created with GPT3" width="808" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This looks way better! We don't have pointers, but it seems that everything else is supported.&lt;/p&gt;

&lt;p&gt;You have all the code available &lt;a href="https://github.com/alesanmed-blog-posts/assistant-language-gpt3"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope more people try something like this and see how far it can get in adding functionality to the language!&lt;/p&gt;

</description>
      <category>prorgramming</category>
      <category>openai</category>
      <category>gpt3</category>
    </item>
    <item>
      <title>¿Qué son y cómo funcionan las impresoras 3D?</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Sun, 18 Sep 2022 08:31:05 +0000</pubDate>
      <link>https://dev.to/alesanchez/que-son-y-como-funcionan-las-impresoras-3d-14cl</link>
      <guid>https://dev.to/alesanchez/que-son-y-como-funcionan-las-impresoras-3d-14cl</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yfLh0JRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1615286922420-c6b348ffbd62%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDV8fDNkJTIwcHJpbnRlcnxlbnwwfHx8fDE2NjM0ODkxOTQ%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yfLh0JRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://images.unsplash.com/photo-1615286922420-c6b348ffbd62%3Fcrop%3Dentropy%26cs%3Dtinysrgb%26fit%3Dmax%26fm%3Djpg%26ixid%3DMnwxMTc3M3wwfDF8c2VhcmNofDV8fDNkJTIwcHJpbnRlcnxlbnwwfHx8fDE2NjM0ODkxOTQ%26ixlib%3Drb-1.2.1%26q%3D80%26w%3D2000" alt="¿Qué son y cómo funcionan las impresoras 3D?" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si prefieres en vídeo, aquí te lo dejo:&lt;/p&gt;

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

&lt;p&gt;Y si lo prefieres en podcast:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://open.spotify.com/embed/episode/43o1hqt6rQfCgCkMjY0pCL" width="100%" height="232px"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Tema interesante hoy la verdad. Vamos a hablar un poquito de qué son las  impresoras 3D, cómo funcionan y qué tipos.&lt;/p&gt;

&lt;p&gt;También veremos qué ventajas tiene cada una y qué se puede hacer con ellas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impresoras de tinta
&lt;/h2&gt;

&lt;p&gt;Para empezar a hablar de ese tema vamos a remontarnos un poquito atrás. Concretamente a ver cómo funcionan  las impresoras 2D de tinta de toda la vida.&lt;/p&gt;

&lt;p&gt;Vamos a centrarnos en las de inyección de tinta porque las de láser funcionan un poquito diferente y no nos va a servir para nada a la hora de hablar de las 3D. Sin embargo las de inyección de tinta sí que nos van a servir.&lt;/p&gt;

&lt;p&gt;Estas lo que tienen es un cabezal con la tinta. Este cabezal se va moviendo y la impresora sabe en qué punto del papel tiene que haber tinta. Concretamente porque en el documento o en la imagen, ese píxel no es blanco. Este cabezal se va moviendo y cuando pasa por uno de esos puntos del papel, echa tinta del color que corresponda. O bien negra, o bien sea mezclando colores para sacar el que debe echar.&lt;/p&gt;

&lt;p&gt;Si alguna vez alguien ha visto una impresora de estas domésticas en funcionamiento, si mirabas un poquito se podía ver cómo funcionaba. Se podía ver cabezal pasando de izquierda a derecha, luego a la la izquierda otra vez, luego a la derecha... haciendo pasadas en cada. Cuando acaba con una línea lo que hace es moverse un poquito hacia abajo y vuelve a pasar por la siguiente. De nuevo, donde tiene que haber tinta, suelta tinta y, donde no tiene que haber tinta, no suelta nada (bastante evidente). Gracias a que el espacio que hay entre cada saltito de una línea a la siguiente es muy pequeño, puede imprimir con una muy buena resolución. Imagina si el tamaño fuese de dos dedos de salto, no podría imprimir nada con una resolución mayor a dos dedos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Impresoras 3D
&lt;/h2&gt;

&lt;p&gt;Para poder imprimir algo en 3D se necesita una cosa que se llama un modelo. Esto no es más que una representación en tres dimensiones del objeto que se quiere imprimir.&lt;/p&gt;

&lt;p&gt;Cuando en una película de animación o algo similar ves un mueble o una casa o incluso un personaje, estás viendo modelos 3D. Pero claro, tú haces este modelo en 3D y se lo mandas a la impresora, pero ella no tiene el concepto este de tres dimensiones, no sabe interpretar esas profundidades, qué está delante o qué está detrás... la solución a esto es basarse en lo que hace una impresora 2D.&lt;/p&gt;

&lt;p&gt;Sabemos que podemos imprimir en un papel en dos dimensiones, y tenemos un modelo que es de tres dimensiones. Es tan sencillo como convertir esas tres dimensiones en dos. ¿Cómo, tes estarás preguntando? Pues para no perder la tridimensionalidad, se parte del modelo 3D y, por ejemplo, de abajo hacia arriba lo va cortando en muchas capas muy finitas. Si luego colocas todas esas capas una encima de la otra, vuelves a tener tu modelo en 3D.&lt;/p&gt;

&lt;h3&gt;
  
  
  Impresoras de filamento
&lt;/h3&gt;

&lt;p&gt;Esta impresoras usan para imprimir  un filamento. Puede ser de muchos materiales pero vamos a asumir, por simplificar mucho, que es un filamento de plástico, así no nos complicamos la vida.&lt;/p&gt;

&lt;p&gt;La impresora tiene un extrusor por el que pasa el filamento, este extrusor se calienta y hace que el filamento se derrita y se pueda usar como una especie de "tinta" para imprimir. Podemos pensar en el extrusor como si fuese los inyectores de tinta de la impresora 2D.&lt;/p&gt;

&lt;p&gt;Como tenemos el modelo en 3D cortado en muchas capas (asumamos que de abajo hacia arriba), lo que va a hacer la impresora es coger esta primera capa, la más baja, y va a ir moviendo el cabezal y poniendo filamento derretido en cada punto de esa capa en la que tenga que haber material. Una vez que ha terminado de hacer esa capa, el extrusor sube un poquito, una mijita muy chica muy chica y pasa a la siguiente capa cortada encima de la anterior. Vuelve a colocar el filamento derretido donde corresponda en esta nueva capa y esto se va repitiendo capa a capa. Al final de este proceso, se habrá construido la figura en 3d que modelamos al principio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QO8-dsJ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/09/hero-image.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QO8-dsJ3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/09/hero-image.webp" alt="¿Qué son y cómo funcionan las impresoras 3D?" width="880" height="495"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Impresora 3D de filamento imprimiendo el modelo de una mano&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Impresoras de Resina
&lt;/h3&gt;

&lt;p&gt;La base es la misma, se coge el modelo en 3d y se corta en muchas capas. A diferencia de las de filamento, que tienen un extrusor que va derritiendo el filamento, aquí lo que se usa es resina líquida. En este caso la impresora es como una caja cerrada en la que se echa la resina resina. Por las características del material de la impresora y de la resina, esta no se pega a ninguna parte, únicamente a una plataforma móvil en la que se irá construyendo la figura.&lt;/p&gt;

&lt;p&gt;Esta plataforma se baja hasta la resina para impregnarla de una capa muy fina. Para endurecer la resina, la impresora tiene un láser de luz ultravioleta. De nuevo, por las características químicas de la resina, cuando la luz ultravioleta incide en ella, se endurece. La impresora solo tiene que apunar con el laser a aquellos puntos donde, en el modelo, hay material y disparar luz UV con el láser. Al terminar con esa capa, vuelve a mojar la plataforma en una capa muy finita de resina (aunque aquí lo importante es que se moja el material endurecido de la capa anterior), y el láser ultravioleta vuelve a tocar donde corresponde en la segunda capa. Al igual que en la de filamento, esto se va repitiendo una y otra vez hasta que se tiene la figura completa impresa.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cymQ6P6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/09/step1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cymQ6P6k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/09/step1.jpg" alt="¿Qué son y cómo funcionan las impresoras 3D?" width="880" height="495"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Impresora de resina&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Aplicaciones
&lt;/h3&gt;

&lt;p&gt;Es muy fácil de diferenciar las figuras que se imprimen con filamento de las que se imprimen con resina. Las de filamentos son muy características porque ves las líneas que ha ido dejando al secarse. Esto se debe a que el filamento se va poniendo en líneas, por así decirlo. En la de resina, por el contrario, se ve como una pieza única, un único bloque de plástico.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NP-btIU9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/09/2021-07-25-00.22.09.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NP-btIU9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.alesanchez.es/content/images/2022/09/2021-07-25-00.22.09.jpg" alt="¿Qué son y cómo funcionan las impresoras 3D?" width="880" height="660"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figura de resina vs figura de filamento&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;En la imagen se aprecia claramente lo que quiero decir. La figura de filamento tiene mucho menos detalle y se ven las marcas horizontales.&lt;/p&gt;

&lt;p&gt;Las impresoras de filamento suelen ser más baratas y son muy útiles para imprimir piezas o modelos que no son de exposición somo tal, sino que los quieres para resolver algún problema, como podría ser un engranaje roto de algún aparato, cuñas para las puertas, etc.&lt;/p&gt;

&lt;p&gt;Para terminar, vamos a ver algunas cosas que se han impreso con impresoras 3D. Por supuesto no ha sido usando plástico, sino combinando muchos materiales, alguno de ellos orgánicos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comida&lt;/li&gt;
&lt;li&gt;Piel&lt;/li&gt;
&lt;li&gt;El taladro funcional en miniatura más pequeño &lt;/li&gt;
&lt;li&gt;A partir de ecografías en 3D se puede imprimir el bebé que llevas dentro antes de que nazca. Esto se hace que los padres puedan cogerlo y verlo.&lt;/li&gt;
&lt;li&gt;¡¡Edificios!!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Y, antes de terminar, si estás buscando comprarte una impresora de este tipo, te dejo una buena comparativa relación calidad-precio &lt;a href="https://gompac.com/tecnologia/mejores-impresoras-3d-calidad-precio-2022/"&gt;aquí&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;La verdad es que es una pasada. Hasta aquí hemos llegado y la verdad es que espero que te haya gustado, que lo hayas disfrutado y que, por supuesto, haya sido útil y divertido.&lt;/p&gt;

&lt;p&gt;Como siempre cualquier comentario, duda o sugerencia que tenga la puedes dejar en un comentario. ¡Hasta la próxima!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Concurrency or Parallelism? Differentiate them</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Thu, 01 Sep 2022 20:54:26 +0000</pubDate>
      <link>https://dev.to/alesanchez/concurrency-or-parallelism-differentiate-them-dg</link>
      <guid>https://dev.to/alesanchez/concurrency-or-parallelism-differentiate-them-dg</guid>
      <description>&lt;p&gt;In this post, I'll try to illustrate the differences between concurrency and parallelism. These terms are usually misused (I did too several times), so let's see if we can finally clear any doubts about this topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a CPU and how does it work?
&lt;/h2&gt;

&lt;p&gt;A CPU is like the brain of a computer. It's where the majority of the operations are done. Also is responsible for executing the tasks we need.&lt;/p&gt;

&lt;p&gt;A CPU can have a single core or multiple cores. Let's imagine that a CPU is a factory, and each core is a worker. The more cores a CPU has, the more work it can perform at the same time.&lt;/p&gt;

&lt;p&gt;This is the key part. Each core can perform only one task at a time. If this point is clear, you already understood half of the topic.&lt;/p&gt;

&lt;h2&gt;
  
  
  So... what is parallelism?
&lt;/h2&gt;

&lt;p&gt;As the word says, it's when multiple tasks are run &lt;strong&gt;in parallel&lt;/strong&gt;. That means that several tasks are run at the same time. If you understood the previous point... how many cores are needed (at minimum) if you want to run two tasks in parallel?&lt;/p&gt;

&lt;p&gt;Since one core can perform only one task at a time, you'll need &lt;strong&gt;at least&lt;/strong&gt; 2 cores. If you have more than two, the rest of the cores are going to be idle, because 1 task -&amp;gt; 1 core.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Kdz3yj6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjd1owcyly21f5d3jatz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Kdz3yj6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fjd1owcyly21f5d3jatz.png" alt="Example of two parallel tasks running on two cores" width="880" height="495"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;h2&gt;
  
  
  Ok, but what is concurrency?
&lt;/h2&gt;

&lt;p&gt;Nice! We understood parallelism, let's dive into concurrency now!&lt;/p&gt;

&lt;p&gt;You can think about concurrency as an &lt;strong&gt;illusion of parallelism&lt;/strong&gt;. Let me explain that.&lt;/p&gt;

&lt;p&gt;Imagine someone working in customer service. That person has to serve two queues of people, but there is only one employee.  So the person decides to go with the first customer in the first queue. If that customer has to fill out a form or perform any other task that doesn't need the attention of the employee, the person goes to the second queue. If the same situation happens or the client in the first queue finishes the task, the employee comes back. Repeating that process creates an illusion of parallelism. As seen from the outside, it may look like the employee is serving both queues at the same time.&lt;/p&gt;

&lt;p&gt;The same thing happens in a CPU. Since we are working with a single core, just one task at a time can be performed. But the CPU, by fast switching between the two tasks, creates an illusion of parallelism.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l3rWH5tY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/853so1jcduqthv2gyf19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l3rWH5tY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/853so1jcduqthv2gyf19.png" alt="Concurrent execution of two tasks in a single core" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You have learned the differences between parallelism and concurrency. You learned that one core can work on just one task at the same time.  If you want to run two tasks in parallel, you need a CPU with (at least) two cores. If your CPU is a single core and want to run two tasks at (almost) the same time, you need to use concurrency. In concurrency, the CPU switches very fast between the two tasks, creating an illusion of parallelism. &lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>concurrency</category>
      <category>parallelism</category>
    </item>
    <item>
      <title>Depurar Python como un Pro</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Mon, 26 Jul 2021 17:53:32 +0000</pubDate>
      <link>https://dev.to/alesanchez/depurar-python-como-un-pro-4f53</link>
      <guid>https://dev.to/alesanchez/depurar-python-como-un-pro-4f53</guid>
      <description>&lt;p&gt;Seguimos con la serie de posts sobre Python. Sigo con el bootcamp de Data Science y Machine Learning de &lt;a href="https://www.corecode.school/" rel="noopener noreferrer"&gt;Core Code School&lt;/a&gt; y en los últimos días hemos estado viendo cómo hacer visualizaciones de datos tremendamente molonas con &lt;a href="https://streamlit.io/" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Durante el proceso de creación de la aplicación web con Streamlit nos encontramos con un problema que impedía ver los datos. Mientras que itentábamos ver la causa salió a colación el tema de la depuración de código y algunos compañeros no sabían lo que era.&lt;/p&gt;

&lt;p&gt;Así que he visto una oportunidad magnífica de explicar lo que es la depuración de código, por qué es útil y cómo hacerlo en las herramientas que usamos de manera más usual en Core.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué es depurar
&lt;/h2&gt;

&lt;p&gt;Lo primero y más importante es explicar y entender qué es eso de depurar el código o depurar un bug. También se suele decir mucho hacer &lt;em&gt;Debug&lt;/em&gt; del código, hacer &lt;em&gt;Debugging&lt;/em&gt; o, en una españolización del término, también puedes escuchar alguna vez &lt;em&gt;Debuggear&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Básicamente, depurar es recorrer exhaustivamente un código para identificar y corregir la causa de un problema.&lt;/p&gt;

&lt;p&gt;Este proceso tiene una parte muy fuerte de observación y otra parte creativa. Normalmente cuando vas depurando no sabes dónde está el fallo y por eso tiene que ir probando y recorriendo todo. Mientras vas depurando, tienes que ir viendo cómo cambian tus variables hasta que veas cuándo se produce el comportamiento anormal o que quieres resolver.&lt;/p&gt;

&lt;p&gt;Para hacer todo esto, tienes muchas herramientas que te ayudan con el proceso.&lt;/p&gt;

&lt;h2&gt;
  
  
   Por qué necesito depurar
&lt;/h2&gt;

&lt;p&gt;La realidad es que no &lt;strong&gt;siempre&lt;/strong&gt; necesitas depurar, pero alguna vez lo necesitarás sin ninguna duda y, cuando eso pase, mejor tener las herramientas y los conocimientos.&lt;/p&gt;

&lt;p&gt;Un método de depuración muy habitual es imprimir mensajes informativos para ver por dónde va pasando el código y qué valores van tomando las variables. Un ejemplo de esto es:&lt;/p&gt;

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

&lt;p&gt;Ahí ves que hay un print para ver el parámetro que se le pasa a la función, es algo muy sencillo y pequeño pero ilustra lo que quiero decir. &lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplos de depuración
&lt;/h2&gt;

&lt;p&gt;Ahora voy ponerte un ejemplo de lo que es depurar en tiempo real, lo que se ve y lo que se puede hacer.&lt;/p&gt;

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

&lt;p&gt;En ese código tengo una lista de frases típicas. Lo que hago es un for que recorra la lista y le aplique un &lt;a href="https://es.wikipedia.org/wiki/Cifrado_C%C3%A9sar" rel="noopener noreferrer"&gt;cifrado césar&lt;/a&gt; a cada una.&lt;/p&gt;

&lt;p&gt;Como puedes ver, a la izquierda de la pantalla está lo que se llama el "inspector", en el que tienes acceso a cada variable y al valor que toma en cada momento.&lt;/p&gt;

&lt;p&gt;Para que el depurador se pare en una línea concreta de tu código tienes que poner lo que se llama un punto de interrupción (en inglés, &lt;strong&gt;breakpoint&lt;/strong&gt;). Esto se hace poniendo el ratón a la izquierda de los números de línea y clicando donde aparece un puntito rojo.&lt;/p&gt;

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

&lt;p&gt;Ese punto está sombreado porque no está puesto, cuando clicas ahí se pone en un rojo más intenso y ya significa que está puesto:&lt;/p&gt;

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

&lt;p&gt;Además, cuando la depuración llega a una función, puedes entrar dentro de ella y depurar esa función paso a paso, como he hecho en el vídeo.&lt;/p&gt;

&lt;p&gt;Incluso en el bucle que hay en la función que hace el cifrado puedes ir letra a letra y ver cómo va calculando el resultado.&lt;/p&gt;

&lt;p&gt;Con este método podrías detectar un bug en tu código y solucionarlo de manera más o menos sencilla.&lt;/p&gt;

&lt;p&gt;Una vez que sabes qué es depurar, te voy a enseñar cómo hacerlo en las herramientas habituales que usamos en &lt;a href="https://www.corecode.school/" rel="noopener noreferrer"&gt;Core&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Depurar en VSCode
&lt;/h2&gt;

&lt;p&gt;La primera de todas es, cómo no, Visual Studio Code. También es la más sencilla de las que vas a ver en el post.&lt;/p&gt;

&lt;p&gt;Si te fijas en la barra izquierda de VSCode, puedes ver que hay un botón que es un signo de &lt;strong&gt;Play&lt;/strong&gt; con un insecto encima (en inglés, un &lt;strong&gt;bug&lt;/strong&gt;):&lt;/p&gt;

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

&lt;p&gt;Púlsalo y te mostrará la vista de depuración. VSCode controla las configuraciones de depuración con un archivo que se llama &lt;code&gt;launch.json&lt;/code&gt; y que se encuentra en la carpeta &lt;code&gt;.vscode&lt;/code&gt; de tu proyecto.&lt;/p&gt;

&lt;p&gt;Si es la primera vez que abres la vista de depuración y no tienes ninguna configuración, verás una vista como esta:&lt;/p&gt;

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

&lt;p&gt;Lo que harás será pulsar donde dice "cree un archivo launch.json". Lo importante es que pulses eso mientras tienes un archivo &lt;code&gt;.py&lt;/code&gt; abierto, porque así VSCode te sugerirá configuraciones para depurar en Python, como ves aquí:&lt;/p&gt;

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

&lt;p&gt;Como ves, VSCode tiene configuraciones predefinidas para varias opciones de Python como depurar un archivo, un módulo o frameworks como Django, Flask o FastApi.&lt;/p&gt;

&lt;p&gt;En este primer ejemplo vas a elegir &lt;strong&gt;Python File&lt;/strong&gt;. Cuando lo selecciones, te creará un archivo &lt;code&gt;launch.json&lt;/code&gt; dentro de la carpeta &lt;code&gt;.vscode&lt;/code&gt; con el siguiente contenido:&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;IntelliSense&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;para&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;saber&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;los&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;atributos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;posibles.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Mantenga&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;el&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;puntero&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;para&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ver&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;las&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;descripciones&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;de&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;los&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;existentes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;atributos.&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Para&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;más&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;información&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;visite:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;https://go.microsoft.com/fwlink/?linkid=&lt;/span&gt;&lt;span class="mi"&gt;830387&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&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="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;"Python: Archivo actual"&lt;/span&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;"python"&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;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${file}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"console"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integratedTerminal"&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="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;Una vez que ese archivo está guardado, puedes volver a la vista de depuración y verás que te aparece una vista distinta a la de antes con una opción con el mismo nombre que aparece en el atributo &lt;code&gt;name&lt;/code&gt; de ese JSON.&lt;/p&gt;

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

&lt;p&gt;Si te sigue apareciendo la misma vista que antes para crear un archivo launch.json, cierra y abre VSCode para que aplique los cambios.&lt;/p&gt;

&lt;p&gt;Una vez tienes esto configurado y algún punto de ruptura puesto, ya puedes darle al play verde que aparece en la vista de depuración, a la izquierda del nombre de la configuración:&lt;/p&gt;

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

&lt;p&gt;Eso deberá lanzarte la depuración y pararse en el primer punto de ruptura que se encuentre mientras ejecuta el código.&lt;/p&gt;

&lt;p&gt;Una vez parado, te aparecerán los llamados controles de depuración que te voy a detallar ahora:&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Seguir hasta el siguiente punto de interrupción. Reanuda la ejecución hasta que encuentre otro punto de ruptura. Ten en cuenta que si el punto está dentro de un bucle y le das al botón 1, se parará en ese mismo punto, pero en la siguiente vuelta del bucle.&lt;/li&gt;
&lt;li&gt;Saltar a la siguiente instrucción, omitiendo procedimientos. Ejecuta la instrucción en la que está parado el depurador actualmente y pasa la siguiente. Ten en cuenta que ejecutar una instrucción implica que se pueden actualizar variables, mantén siempre un ojo en la parte de inspección de variables (barra izquierda).&lt;/li&gt;
&lt;li&gt;Saltar a la siguiente instrucción, sin omitir procedimientos. Esto hace exactamente lo mismo que el botón anterior, salvo que salta a la siguiente instrucción inmediatamente. Puede parecer lo mismo, pero hay una diferencia. Si estás en una línea que ejecuta una función, el botón anterior &lt;em&gt;no&lt;/em&gt; va a entrar dentro de la función, sino que va a omitirla (omitir el procedimiento) y saltará a la siguiente. Este botón entrará dentro. Aquí puedes ver la diferencia:
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/w6AU8EMGwPk"&gt;
&lt;/iframe&gt;
&lt;/li&gt;
&lt;li&gt;Sale de la función que estás depurando. Es útil si entras en una función creyendo que puede estar el problema ahí y cuando vas por la mitad ves que no está ahí, en vez de poner otro punto de ruptura o empezar de nuevo, simplemente sales de esa función y sigues adelante. Si estás en un código que no está dentro de ninguna función y sales, la depuración continuará hasta el siguiente punto de interrupción, como si hubieras dado al botón 1.&lt;/li&gt;
&lt;li&gt;Reinicia el proceso de depuración. Lo mismo que parar y volver a empezar.&lt;/li&gt;
&lt;li&gt;Para el proceso de depuración. Para la ejecución sin ejecutar nada más, no termina el proceso de manera normal, sino que corta la ejecución.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Consejo de Pro: Explora la pestaña "Consola de Depuración". Cuando estás parado en un punto de ruptura, puedes ejecutar código Python desde ahí y ver el resultado inmediatamente. Puedes anticiparte a errores o bugs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Depurar en Jupyter
&lt;/h2&gt;

&lt;p&gt;Ahora que sabes depurar en VSCode, vamos a probar con Jupyter. Lo cierto es que Jupyter Notebook no permite hacer depuración pero &lt;a href="https://jupyterlab.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Jupyter Lab&lt;/a&gt; sí.&lt;/p&gt;

&lt;p&gt;Para instalarlo puedes seguir las &lt;a href="https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html" rel="noopener noreferrer"&gt;instrucciones oficiales&lt;/a&gt;. Lo puedes instalar con Conda sin problema.&lt;/p&gt;

&lt;p&gt;Una vez instalado, hay que poner un par de paquetes de python y alguna extensión de Jupyter Lab.&lt;/p&gt;

&lt;p&gt;Lo primero que vas a instalar es un kernel de Python compatible con la depuración, en este caso &lt;a href="https://github.com/jupyter-xeus/xeus-python" rel="noopener noreferrer"&gt;Xeus&lt;/a&gt;. Para instalarlo, ejecuta en una terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;conda install -c conda-forge xeus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez está, puedes instalar la extensión de depuración, para esto ejecuta en una terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jupyter labextension install @jupyterlab/debugger
jupyter lab build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez instalada la extensión y terminado el &lt;code&gt;build&lt;/code&gt;, ejecuta Jupyter lab con el comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jupyter lab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez lanzado Jupyter, abre el notebook que quieras depurar. Ahora tienes que cambiar el kernel de python al que hemos instalado, XPython. Esto lo puedes cambiar en el selector de la esquina superior derecha.&lt;/p&gt;

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

&lt;p&gt;Cuando cliques, debes ver una ventana para seleccionar el kernel que quieres, elige XPython:&lt;/p&gt;

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

&lt;p&gt;Ahora verás que hay 2 cosas nuevas, relacionadas con la depuración:&lt;/p&gt;

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

&lt;p&gt;Lo primero es un interruptor al lado de un icono de un insecto, y lo segundo es un botón con el mismo icono del insecto. Primero activa el interruptor, eso mostrará una barra para poner puntos de interrupción y además mostrará una barra a la izquierda con información similar a la que teníamos en VSCode.&lt;/p&gt;

&lt;p&gt;Puedes poner puntos de ruptura de la misma manera que en VSCode, clicando a la izquierda del número de línea:&lt;/p&gt;

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

&lt;p&gt;Una vez tienes el punto de ruptura, puedes ejecutar la celda de manera normal, y se parará en el punto:&lt;/p&gt;

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

&lt;p&gt;A la izquierda tienes lo mismo que había en VSCode, el inspector de variables, los mismos botones para controlar la depuración y una lista de los puntos de ruptura.&lt;/p&gt;

&lt;p&gt;Si pulsas el botón para ejecutar la instrucción entrando en funciones y la función está en otra celda, Jupyter se encargará de que salte a la celda correcta y siga la depuración normal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Depurar Streamlit
&lt;/h2&gt;

&lt;p&gt;Otra herramienta que usamos en Core es &lt;a href="https://streamlit.io/" rel="noopener noreferrer"&gt;Streamlit&lt;/a&gt;. Como también puede haber errores al desarrollar una app de Streamlit, vas a aprender a depurar eso también.&lt;/p&gt;

&lt;p&gt;Lo único que hace falta es una configuración nueva para nuestro &lt;code&gt;launch.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si lo abres, verás que la propiedad &lt;code&gt;configurations&lt;/code&gt; es un array. Ahí puedes poner todas las configuraciones que quieras. Ya debes tener una, así que añade esta:&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;"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;"Python: Streamlit"&lt;/span&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;"python"&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;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"streamlit.cli"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"${file}"&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="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;El nombre de esa configuración será &lt;code&gt;Python: Streamlit&lt;/code&gt;, decimos que la depuración es python y que vamos a lanzar algo. En vez de lanzar un archivo como antes, ahora lo que vamos a lanzar es un módulo, en este caso &lt;code&gt;stramlit.cli&lt;/code&gt;, que básicamente es el intérprete de comandos de Streamlit. Y, por último, vamos a pasarle al cli los argumentos &lt;code&gt;run ${file}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;VSCode sustituirá &lt;code&gt;${file}&lt;/code&gt; por el archivo que tengas abierto al lanzar esa depuración. Si no quieres que sea así y siempre quieres que lance el mismo archivo, puedes sustituir eso por el archivo que necesites.&lt;/p&gt;

&lt;p&gt;Esa configuración es equivalente a llamar a &lt;code&gt;streamlit run ${file}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ahora solo tendrás que poner tus puntos de interrupción y lanzar la depuración.&lt;/p&gt;

&lt;h2&gt;
  
  
  Depurar Flask
&lt;/h2&gt;

&lt;p&gt;Depurar Flask es igual de sencillo que Streamlit. Solo necesitas añadir una configuración de depuración al &lt;code&gt;launch.json&lt;/code&gt; y listo.&lt;/p&gt;

&lt;p&gt;En este caso, tienes que añadir:&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;"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;"Python: Flask"&lt;/span&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;"python"&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;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"flask"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"FLASK_APP"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"FLASK_ENV"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"FLASK_DEBUG"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&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;"args"&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;"run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--no-debugger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--no-reload"&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;"jinja"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;Ahí lo que le dices es que la configuración se llama &lt;code&gt;Python: Flask&lt;/code&gt;, que es de tipo python y que quieres lanzar un módulo, que es flask.&lt;/p&gt;

&lt;p&gt;Con &lt;code&gt;env&lt;/code&gt; se ponen una serie de variables de entorno que le indican a flask qué archivo tiene que ejecutar, en qué entorno está y desactiva el modo de depuración (porque ya lo gestiona VSCode).&lt;/p&gt;

&lt;p&gt;Además, igual que antes, añade una serie de argumentos al comando flask para configurar la ejecución y añade un parámetro &lt;code&gt;jinja&lt;/code&gt; que es el motor de plantillas que usa Flask, para permitir depurar eso también. &lt;/p&gt;

&lt;p&gt;Si tú no vas a usar plantillas, puedes eliminar esa opción.&lt;/p&gt;

&lt;p&gt;De nuevo, una vez tienes eso, solo necesitas activar tus puntos de ruptura y ejecutar la depuración.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;Ahora sabes lo que es depurar, por qué es importante y cómo hacerlo en algunas herramientas habituales en el desarrollo y en Python, ya no hay quien te pare.&lt;/p&gt;

&lt;p&gt;Recuerda dejar en los comentarios cualquier duda o sugerencia que tengas y mirar los cursos de &lt;a href="https://www.corecode.school/" rel="noopener noreferrer"&gt;Core&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nos vemos en el próximo post!&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>debug</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>6 Cositas sabrosas que hacer con Python</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Thu, 15 Jul 2021 16:10:31 +0000</pubDate>
      <link>https://dev.to/alesanchez/6-cositas-sabrosas-que-hacer-con-python-2ndd</link>
      <guid>https://dev.to/alesanchez/6-cositas-sabrosas-que-hacer-con-python-2ndd</guid>
      <description>&lt;p&gt;Como ya sabes por mis posts anteriores, llevo ya un par de meses embarcado en un Bootcamp de Machine Learning y Data Science con las buenas gentes de &lt;a href="https://www.corecode.school/"&gt;Core School&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Como es natural, el lenguaje principal es Python. Precisamente por eso, vengo con un magnífico post de 6 cosas magníficas que debes saber de Python!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Intercambia valores de variables en una sola sentencia
&lt;/h2&gt;

&lt;p&gt;Esto viene directamente de la posibilidad de hacer una asignación múltiple a partir de una tupla. Mira, por ejemplo, este código&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@alesanmed/VarSwap?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;Como ves, puedes asignar las 2 variables a la vez teniendo una tupla. Si la tupla que usas para asignar las variables contiene, a su vez, otra dos variables, debe ser igual de válido.&lt;/p&gt;

&lt;p&gt;Siguiendo la misma lógica, puedes usar las dos variables que quieres intercambiar dentro de la tupla, en orden inverso. &lt;/p&gt;

&lt;p&gt;Y, por último, como en Python puedes omitir los paréntesis al crear una tupla, puedes dejarlo mucho más bonito (todos los pasos en el código).&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@alesanmed/VarSwapV4?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  2. Conoce y usa las funciones &lt;em&gt;built-in&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;¿Por qué es importante? Porque esas funciones de Python están escritas directamente en C. Si tú implementas esas funciones a mano, tendrán que interpretarse en código Python, lo cual es más lento.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.python.org/3/library/functions.html"&gt;Aquí&lt;/a&gt; tienes todas las funciones &lt;em&gt;built-in&lt;/em&gt; de Python. Un resumen de ellas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oo6qliOo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1kt1ubfdlrnpdhkgo24l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oo6qliOo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1kt1ubfdlrnpdhkgo24l.png" alt="Lista con las built-in functions de python"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Usa &lt;code&gt;in&lt;/code&gt; para buscar en listas
&lt;/h2&gt;

&lt;p&gt;Esto va muy de la mano del punto anterior. En lugar de usar &lt;code&gt;find&lt;/code&gt; o de implementar tu propia función de búsqueda, usa &lt;code&gt;in&lt;/code&gt; siempre que quieras comprobar si un elemento está en una lista. Es muy idiomático y limpio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; 1 in [1, 2, 3]
True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  4. Haz buenas migas con los &lt;em&gt;list comprehensions&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Esta es otra herramienta muy característica de Python. La base de esto es construir listas de una manera muy cómoda. La sintaxis básica es:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lista&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Si quieres usar un condicional, puedes hacerlo.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lista&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;condicion&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Y si quieres un &lt;code&gt;if-else&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;condicion&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;otro_valor&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lista&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ahora toca ver unos cuantos ejemplos.&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@alesanmed/ListComprehension?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Usa funciones generadoras para ahorrar memoria
&lt;/h2&gt;

&lt;p&gt;El ejemplo más clásico de las funciones generadoras es &lt;code&gt;range&lt;/code&gt;. No es lo mismo tener una función que te dice cómo generar 1000 valores, que tener 1000 valores guardados. La prueba:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getsizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;48&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getsizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="mi"&gt;8056&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;En la primera línea lo que hay es un objeto que genera 1000 números bajo demanda, pesa 48 bytes. Sin embargo, la segunda línea lo que tiene es una lista con esos 1000 números en memoria, pesando 8 Kb.&lt;/p&gt;

&lt;p&gt;Tú puedes hacer funciones generadoras usando la palabra &lt;code&gt;yield&lt;/code&gt;. Te voy a poner un ejemplo muy tonto pero ilustrativo.&lt;/p&gt;


&lt;div class="ltag__replit"&gt;
  &lt;iframe height="550px" src="https://repl.it/@alesanmed/Generator-functions?lite=true"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTA: Cuando tienes un generador (excepto con range), no puedes hacer &lt;code&gt;generador[10]&lt;/code&gt;, pues no está todo el conjunto de elementos en memoria, pero sí que puedes iterarlo con un for o list comprehension. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  6. Python 3.8 o más: Operador &lt;em&gt;walrus&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;A partir de la versión 3.8 Python tiene un operador que es este &lt;code&gt;:=&lt;/code&gt; y se llama el operador "morsa" (porque parece una morsa tumbada de lado).&lt;/p&gt;

&lt;p&gt;Este operador te permite hacer una asignación dentro de otra expresión. Ejemplo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;numero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;potencia&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numero&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;potencia&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ese código va a imprimir &lt;code&gt;4&lt;/code&gt;, porque se está haciendo la asignación de la variable potencia dentro de la misma expresión del if.&lt;/p&gt;

&lt;p&gt;Otro ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Escribe 'exit' para salir"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"exit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ese bucle &lt;code&gt;while&lt;/code&gt; se va a ejecutar eternamente hasta que el usuario escriba &lt;em&gt;exit&lt;/em&gt; pero, además, tendrás acceso a lo que escriba el usuario en la variable &lt;code&gt;user_input&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recapitulación
&lt;/h2&gt;

&lt;p&gt;Básicamente lo que has aprendido es que debes o puedes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intercambiar valores de variables en una sola sentencia&lt;/li&gt;
&lt;li&gt;Conocer y usa las funciones &lt;em&gt;built-in&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Usar &lt;code&gt;in&lt;/code&gt; para buscar en listas&lt;/li&gt;
&lt;li&gt;Llevarte bien con los &lt;em&gt;list comprehensions&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Usar funciones generadoras para ahorrar memoria&lt;/li&gt;
&lt;li&gt;Si estás en Python 3.8 o más: Operador &lt;em&gt;walrus&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Espero que te haya parecido interesante. Si conoces más cosas del estilo que se puedan hacer con Python, te leo en los comentarios!&lt;/p&gt;

&lt;p&gt;Recuerda entrar en la web de &lt;a href="https://www.corecode.school/"&gt;Core&lt;/a&gt; si quieres aprender Data Sciente/Machine Learning o aprender a programar "Cloud Native"!&lt;/p&gt;

&lt;p&gt;Hasta el siguiente post!&lt;/p&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>principiante</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Trabajando a 100 por hora en Jupyter Notebook</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Sat, 10 Jul 2021 12:40:08 +0000</pubDate>
      <link>https://dev.to/alesanchez/trabajando-a-100-por-hora-en-jupyter-notebook-3bfj</link>
      <guid>https://dev.to/alesanchez/trabajando-a-100-por-hora-en-jupyter-notebook-3bfj</guid>
      <description>&lt;h2&gt;
  
  
  Qué es Jupyter
&lt;/h2&gt;

&lt;p&gt;Para el que no lo conozca, el &lt;a href="https://jupyter.org/" rel="noopener noreferrer"&gt;Proyecto Jupyter&lt;/a&gt; es una herramienta diseñada para crear documentos con código, ecuaciones, imágenes... que puedes ejecutar en vivo.&lt;/p&gt;

&lt;p&gt;Es tremendamente útil con fines académicos y con el objetivo de compartir código.&lt;/p&gt;

&lt;p&gt;Es muy usado para investigación y enseñanza, como es el caso que nos ocupa.&lt;/p&gt;

&lt;p&gt;En mi caso, uso Jupyter en el curso de Data Science y Machine Learning que estoy haciendo en la academia &lt;a href="https://www.corecode.school/" rel="noopener noreferrer"&gt;Core Code School&lt;/a&gt;. La verdad, los cursos molan bastante y no necesitas conocimiento previo para embarcarte en ellos (toma publi, Marc).&lt;/p&gt;

&lt;p&gt;Una vez hechas las presentaciones, vamos a ver cuál es el objetivo de este post.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Por qué modificar lo que viene de base?
&lt;/h2&gt;

&lt;p&gt;Creo que la respuesta a esta pregunta es bastante obvia... &lt;del&gt;porque puedo&lt;/del&gt; para intentar mejorar la experiencia con la herramienta.&lt;/p&gt;

&lt;p&gt;La idea de todo esto es modificar la interfaz y el comportamiento de Jupyter para mejorar tu productividad y el flujo de trabajo de forma que puedas hacer el mismo trabajo en menos tiempo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisitos
&lt;/h2&gt;

&lt;p&gt;No es parte de este post explicar cómo funciona Jupyter ni cómo instalarlo. Se asume que tienes python y Jupyter en tu equipo (preferiblemente con &lt;a href="https://www.anaconda.com/products/individual" rel="noopener noreferrer"&gt;Anaconda&lt;/a&gt;) y que sabes manejarte con lo básico en jupyter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalar los paquetes
&lt;/h2&gt;

&lt;p&gt;Antes de empezar necesitas instalar unos paquetes de python para que Jupyter se entienda con las extensiones y los temas.&lt;/p&gt;

&lt;p&gt;Para poder gestionar temas necesitas instalar &lt;a href="https://github.com/dunovank/jupyter-themes" rel="noopener noreferrer"&gt;jupyter-themes&lt;/a&gt; con el comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;jupyterthemes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez tienes eso, toca ir a por el paquete para gestionar extensiones. En este caso es &lt;a href="https://github.com/ipython-contrib/jupyter_contrib_nbextensions" rel="noopener noreferrer"&gt;jupyter_contrib_nbextensions&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;conda &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; conda-forge jupyter_contrib_nbextensions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y una vez que tienes ese paquete, falta instalar los archivos necesarios en Jupyter. Afortunadamente, el paquete expone un comando para eso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jupyter contrib nbextension &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ya lo tienes todo listo para empezar a ponerlo a tu gusto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo primero es lo primero
&lt;/h2&gt;

&lt;p&gt;Las extensiones y la productividad están muy bien, pero aquí hemos venido a la fantasía, y por eso voy a empezar con los temas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: Te recomiendo parar Jupyter y borrar la caché del navegador antes de cambiar el tema.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;La extensión de los temas expone el comando &lt;code&gt;jt&lt;/code&gt; para gestionarla. Para listar los temas disponibles usa el comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jt &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En mi caso tengo disponibles los temas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Available Themes: 
   chesterish     
   grade3
   gruvboxd
   gruvboxl
   monokai
   oceans16
   onedork
   solarizedd
   solarizedl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A mi, personalmente, el que más me gustó es &lt;code&gt;oceans16&lt;/code&gt;. Para activarlo se usa el comando &lt;code&gt;jt -t [nombre_del_tema]&lt;/code&gt;. Pero hay otra serie de opciones que se pueden usar para cambiar la fuente y muchas cosas más.&lt;/p&gt;

&lt;p&gt;En mi caso, voy a cambiar la fuente del código a &lt;code&gt;FiraCode&lt;/code&gt; y la del texto y el markdown a &lt;code&gt;Merriweather&lt;/code&gt;. Para eso voy a usar los a argumentos &lt;code&gt;-f&lt;/code&gt; (fuente del código), &lt;code&gt;-nf&lt;/code&gt; (fuente del notebook) y &lt;code&gt;-tf&lt;/code&gt; (fuente del texto/makrdown):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jt &lt;span class="nt"&gt;-t&lt;/span&gt; oceans16 &lt;span class="nt"&gt;-f&lt;/span&gt; firacode &lt;span class="nt"&gt;-nf&lt;/span&gt; merriserif &lt;span class="nt"&gt;-tf&lt;/span&gt; merriserif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Puedes cambiar el tamaño de la fuente, qué elementos se muestran y &lt;a href="https://github.com/dunovank/jupyter-themes#command-line-usage" rel="noopener noreferrer"&gt;muchas cosas más&lt;/a&gt;. En mi caso, la configuración que he elegido es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jt &lt;span class="nt"&gt;-t&lt;/span&gt; oceans16 &lt;span class="nt"&gt;-f&lt;/span&gt; firacode &lt;span class="nt"&gt;-nf&lt;/span&gt; merriserif &lt;span class="nt"&gt;-tf&lt;/span&gt; merriserif &lt;span class="nt"&gt;-fs&lt;/span&gt; 95 &lt;span class="nt"&gt;-altp&lt;/span&gt; &lt;span class="nt"&gt;-tfs&lt;/span&gt; 11 &lt;span class="nt"&gt;-nfs&lt;/span&gt; 115 &lt;span class="nt"&gt;-cellw&lt;/span&gt; 88% &lt;span class="nt"&gt;-T&lt;/span&gt; &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="nt"&gt;-kl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y queda así:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6vbofjoljewpskkb7zy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6vbofjoljewpskkb7zy.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Ahora sí, las extensiones
&lt;/h2&gt;

&lt;p&gt;Una vez que ya lo tienes bonito, a por las extensiones para trabajar mejor. &lt;/p&gt;

&lt;p&gt;Si, como yo, tienes la versión de Jupyter 6, vas a tener que desactivar esta casilla en la pestaña &lt;code&gt;NbExtensions&lt;/code&gt;:&lt;/p&gt;

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

&lt;p&gt;Para poder instalar las extensiones. Esto es porque todas las extensiones ponen que son para Jupyter 4 y 5. Sin embargo, yo las he probado con la versión 6 y funcionan todas. &lt;/p&gt;

&lt;p&gt;Ahora sí, sin más rodeos, vamos con ellas (las que yo tengo).&lt;/p&gt;
&lt;h3&gt;
  
  
  Tree Filter
&lt;/h3&gt;

&lt;p&gt;Esta extensión añade una barra de búsqueda a la vista de archivos de Jupyter. Esto te permite buscar archivos o carpetas de manera mucho más rápida y sencilla.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoyv8497ltb9x7ihvfov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faoyv8497ltb9x7ihvfov.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Table of Contents (2)
&lt;/h3&gt;

&lt;p&gt;Esta extensión hace lo que promete. Pone de manera visual el índice del notebook para que puedas tener una navegación rápida:&lt;/p&gt;

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

&lt;p&gt;Para activarla y desactivarla sólo tienes que clicar el botón con el símbolo de la lista en la barra de herramientas. &lt;/p&gt;

&lt;p&gt;Desde la pestaña de &lt;code&gt;NbExtensions&lt;/code&gt; puedes configurar la apariencia, cuántos subniveles se muestran, etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  Collapsible Headers
&lt;/h3&gt;

&lt;p&gt;Parecido al anterior. Te permite ocultar secciones completas contrayendo su cabecera. Con esto puedes ocultar el contenido de las secciones que no necesites para navegar mucho más rápido por el notebook.&lt;/p&gt;

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

&lt;p&gt;Con la flecha izquierda contraes la cabecera de la celda seleccionada y con la derecha la expandes. De nuevo, tienes más configuraciones desde la pestaña de extensiones.&lt;/p&gt;
&lt;h3&gt;
  
  
  Snippets
&lt;/h3&gt;

&lt;p&gt;Esta es una muy simple pero que me parece realmente útil. Puedes definirte fragmentos de código para colocar con un click en una celda.&lt;/p&gt;

&lt;p&gt;La configuración no es tan sencilla como en las demás, pues tienes que definir los snippets en un archivo JSON llamado &lt;code&gt;snippets.json&lt;/code&gt; y colocarlo en la carpeta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$(jupyter --data-dir)/nbextensions/snippets/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si, por ejemplo, quieres un snippet para importar numpy y pandas llamado &lt;code&gt;np, pandas&lt;/code&gt; definirías un JSON como el que sigue:&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;"snippets"&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="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;"name"&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;"np, pandas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"code"&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="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"import numpy as np"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"import pandas"&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="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="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;Ahora podremos incrustar nuestro snippet usando el menú de la barra de herramientas:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Initialization Cells
&lt;/h3&gt;

&lt;p&gt;Muy de la mano con la de snippets se puede usar esta. Esta extensión te permite marcar algunas celdas como "celdas de inicialización", para ejecutarlas automáticamente al abrir un notebook, o a mano, o cuando prefieras.&lt;/p&gt;

&lt;p&gt;Lo primero que hay que hacer es mostrar la casilla de la extensión a través del menú &lt;em&gt;View &amp;gt; Cell Toolbar &amp;gt; Initialization Cell&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Una vez hecho eso, ya podrás marcar casillas como inicialización:&lt;/p&gt;

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

&lt;p&gt;Y, para lanzarlas todas, solo tendrás que clicar el icono de la calculadora de la barra de herramientas.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Autopep8
&lt;/h3&gt;

&lt;p&gt;No hay mucho que decir. Te permite formatear el código de una celda acorde a las reglas de autopep8.&lt;/p&gt;

&lt;p&gt;Para hacerlo, se puede usar el mazo que hay en la barra de tareas:&lt;/p&gt;

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

&lt;p&gt;Otra opción (la que yo he hecho) es configurar un atajo de teclado para formatear una celda. Desde la página de extensiones, configura la opción &lt;em&gt;Hotkey to use to prettify the selected cell(s)&lt;/em&gt; con el atajo que prefieras. En mi caso he usado Ctrl+Alt+F.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: Para que funcione, necesitas tener instalada la extensión &lt;code&gt;autopep8&lt;/code&gt; en tu entorno. Puedes hacerlo con &lt;code&gt;pip install autopep8&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Comment/Uncomment Hotkey
&lt;/h3&gt;

&lt;p&gt;A esta no voy a darle muchas vueltas. Te permite definir un atajo de teclado para comentar una línea o un bloque de código.&lt;/p&gt;

&lt;p&gt;Yo lo tengo configurado con el atajo &lt;code&gt;Ctrl+Shift+7&lt;/code&gt;, igual que Visual Studio Code.&lt;/p&gt;

&lt;h3&gt;
  
  
  ExecuteTime
&lt;/h3&gt;

&lt;p&gt;Esta extensión es más informativa que otra cosa. Te añade una línea debajo de la celda con el tiempo que ha tardado en ejecutarse.&lt;/p&gt;

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

&lt;p&gt;Esta extensión permite configurar el formato en el que aparecen las marcas temporales y cuándo se limpian. &lt;/p&gt;

&lt;h3&gt;
  
  
  Variable Inspector
&lt;/h3&gt;

&lt;p&gt;Tampoco deja mucho a la imaginación. Cuando pulsas el botón con una mirilla de la barra de herramientas, te va a abrir una ventana flotante con las variables que tienes ahora mismo y sus valores.&lt;/p&gt;

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

&lt;p&gt;Esa ventana la puedes actualizar, minimizar y cerrar :) Muy útil para hacer una suerte de depuración.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hinterland
&lt;/h3&gt;

&lt;p&gt;Esta extensión lo que hace es extender una funcionalidad que ya tiene Jupyter. Cuando vas escribiendo código, puedes autocompletar pulsando Ctrl + Espacio. Esta extensión lo que hace es que el autocomlpetado (Intellisense) funcione automáticamente mientras escribes, como en casi cualquier IDE.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Scratchpad
&lt;/h3&gt;

&lt;p&gt;Por último, esta extensión te permite abrir una especie de celda aparte en la que puedes ejecutar código para probar, volátil.&lt;/p&gt;

&lt;p&gt;En esa celda aparte tienes acceso a todas las variables del notebook, tanto para consulta como para modificación. Puedes ver un &lt;a href="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ro3ipo4bfo05rvg5ftsy.gif" rel="noopener noreferrer"&gt;vídeo&lt;/a&gt; de cómo funciona sacado directamente desde su documentación.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;Pues no mucho más que decir :). Ahora tienes tu Jupyter precioso y echas fuego por las orejas cuando trabajas.&lt;/p&gt;

&lt;p&gt;Si tienes más extensiones o flujos de trabajo que merezcan la pena compartir, te leo en los comentarios.&lt;/p&gt;

&lt;p&gt;Y, por supuesto, visita la página de &lt;a href="https://www.corecode.school/" rel="noopener noreferrer"&gt;Core Code School&lt;/a&gt; para ver sus cursos!! &lt;/p&gt;

</description>
      <category>jupyter</category>
      <category>python</category>
    </item>
    <item>
      <title>La relación entre una Lambda de Python y los Simpsons</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Wed, 23 Jun 2021 15:00:39 +0000</pubDate>
      <link>https://dev.to/alesanchez/la-relacion-entre-una-lambda-de-python-y-los-simpsons-5797</link>
      <guid>https://dev.to/alesanchez/la-relacion-entre-una-lambda-de-python-y-los-simpsons-5797</guid>
      <description>&lt;p&gt;Pues, aparentemente, has leído bien. Hace aproximadamente un mes empecé un Bootcamp de Big Data y Machine Learning en &lt;a href="https://www.corecode.school/bootcamp/big-data-machine-learning"&gt;Core Scool&lt;/a&gt; que está siendo una pasada (casi no se ha notado la publicidad). El caso es que en una de las clases se nos presentó el siguiente código cuando hablábamos de &lt;a href="https://en.wikipedia.org/wiki/Currying"&gt;currying&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;potencias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;potencias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;potencias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Todos en clase pensamos (ilusos de nosotros...) que el resultado de ese print iba a ser 16 (

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;242^4&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
) pero cuál fue nuestra sorpresa (y la tuya si pruebas ese código) al ver que el resultado era nada más y nada menos que 65536. Pero... ¿por qué?&lt;/p&gt;

&lt;p&gt;Para resolver esa cuestión tengo que hablar del &lt;code&gt;scope&lt;/code&gt; y, para eso, voy a usar a Los Simpons. Vamos al lío.&lt;/p&gt;
&lt;h2&gt;
  
  
  A por las metáforas
&lt;/h2&gt;

&lt;p&gt;Podría hacerte una definición técnica de lo que es el scope, cómo funciona y cómo afecta, pero la verdad es que ese no es mi estilo en absoluto, así voy con una metáfora.&lt;/p&gt;

&lt;p&gt;Como definición súper general, simplificada y (si la analizas con detalle) parcialmente incorrecta, puedo decir que el scope es una forma que tiene python (y prácticamente cualquier lenguaje) de compartimentar los accesos a las variables.&lt;/p&gt;

&lt;p&gt;Dicho esto, imagina que el código es una casa. Concretamente, la casa de los Simpsons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O5tAZhcq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ezahlpg9ckariyakk3b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O5tAZhcq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ezahlpg9ckariyakk3b.jpg" alt="Plano simpsons" width="880" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En esa casa hay distintas habitaciones e incluso distintas plantas. Imagina también (por simplificar) que todas las estancias son independientes entre sí y que, lo único común a todas ellas son los pasillos y las escaleras.&lt;/p&gt;

&lt;p&gt;Y, por último, imagina que si tú estás en una habitación y necesitas algo, solo puedes ir a buscarlo &lt;strong&gt;saliendo&lt;/strong&gt; de habitaciones.&lt;/p&gt;

&lt;p&gt;Con esto vas a entender el scope perfectamente. Trasladando esto a código, podríamos decir que cada habitación de la casa es un scope distinto. Por simplicidad, vamos a quedarnos solo con la planta de arriba. Si pinto los scopes que habría en la casa de Los Simpsons, quedaría algo como:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h7imA_XA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwjx7hqxutlqewjbt0io.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h7imA_XA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwjx7hqxutlqewjbt0io.png" alt="Plano de la casa con scopes superpuestos" width="880" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si te fijas, cada habitación tiene su propio color, porque es un scope distinto. Incluso las habitaciones que están dentro de otras (el baño que está dentro de la habitación de Homer y Marge), ¡tienen su propio color!&lt;/p&gt;

&lt;p&gt;Una cosa más es que todo el pasillo y las escaleras tienen el mismo scope, el rojo intenso.&lt;/p&gt;

&lt;p&gt;Si yo te digo que como tienes una cama en la habitación de Bart y otra en la de Lisa, tienes 2 camas juntas, me llamarías loco, ¿verdad? Porque no están juntas, están en habitaciones (scopes) diferentes. Pues con las variables es lo mismo.&lt;/p&gt;

&lt;p&gt;Vamos a detallar esto un poco más, colocando objetos en algunas habitaciones:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d_dQUBky--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oznc6kitfmkmoirwc50r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d_dQUBky--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oznc6kitfmkmoirwc50r.png" alt="Plano de la casa con objetos superpuestos" width="880" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Puedes ver que he colocado una bici en el cuarto de Homer y Marge, un jarrón (ánfora) en el de Bart y un tambor en el pasillo.&lt;/p&gt;

&lt;p&gt;Ahora imagina que, como dijimos antes, no puedes ir a buscar nada entrando a otra habitación, solo saliendo. Si estuvieses en el cuarto de Lisa y necesitases un jarrón, ¿podrías ir al cuarto de Bart a por él? Veamos...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sales de la habitación de Lisa al pasillo ✔&lt;/li&gt;
&lt;li&gt;Entras al cuarto de Bart ❌&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Has tenido que entrar en una habitación, así que no puedes ir. Por lo tanto podemos decir que, estando en el cuarto de Lisa, no tienes ningún jarrón.&lt;/p&gt;

&lt;p&gt;Vamos a intentar lo mismo, desde le baño de la habitación de Homer y Marge, pero con la bici.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sales del baño a la habitación de Homer y Marge ✔&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ya tienes la bici!! Y, una vez que la tienes, puedes usarla todo lo que necesites.&lt;/p&gt;

&lt;p&gt;Una última prueba! Vamos a intentar ir a por el tambor desde el baño de Homer y Marge:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sales del baño a la habitación de Homer y Marge ✔&lt;/li&gt;
&lt;li&gt;Sales de la habitación al pasillo ✔&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pues también puedes! Entonces, como regla general puedo decir que, desde cualquier habitación, puedes coger lo que esté en el pasillo.&lt;/p&gt;

&lt;p&gt;Sin embargo no al contrario. Desde el pasillo, no puedes coger nada de ninguna habitación (porque no puedes entrar).&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Qué tiene todo esto que ver con Python?
&lt;/h2&gt;

&lt;p&gt;Lo bonito de todo esto es que es aplicable a Python y a (prácticamente) cualquier lenguaje moderno.&lt;/p&gt;

&lt;p&gt;Si el lenguaje solo tuviese un único scope, desde cualquier parte del código podrías modificar cualquier variable y sería un poco caótico y difícil de depurar.&lt;/p&gt;

&lt;p&gt;En Python hay 4 scopes distintos y hay un acrónimo para recordarlos: LEGB. Son las siglas (en inglés) de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local&lt;/li&gt;
&lt;li&gt;Envoltura (Enclosing)&lt;/li&gt;
&lt;li&gt;Global&lt;/li&gt;
&lt;li&gt;Incorporado (Built-in)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Cómo se crea un scope en python
&lt;/h3&gt;

&lt;p&gt;Python crea scopes cuando se define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Una función &lt;code&gt;lambda&lt;/code&gt;: Cuando haces &lt;code&gt;lambda x: print(x)&lt;/code&gt; esa lambda está definiendo un scope local en el que existe la variable &lt;code&gt;x&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Una función: Cuando creas una función con la palabra &lt;code&gt;def&lt;/code&gt;, estás creando un scope. En el siguiente código:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param_2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;param_1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;param_2&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Estás creando una función que define un scope en el que se definen las variables &lt;code&gt;param_1&lt;/code&gt;, &lt;code&gt;param_2&lt;/code&gt; y &lt;code&gt;add&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clases: Al definir una clase con la palabra reservada &lt;code&gt;class&lt;/code&gt;, también se crea un scope. En este caso es un poco especial porque desde fuera sí puedes acceder al scope de la clase (más o menos). Así que vamos a dejar este caso aparte.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En cualquiera de estos 3 casos, estarás creando un scope local y, por tanto, un código como este:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;local_scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;local_scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hola"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# &amp;gt;&amp;gt; "Hola"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Funciona perfectamente y estaría creando un scope local en &lt;code&gt;local_scope&lt;/code&gt; que contendría la variable &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANTE&lt;/strong&gt;: Un scope se crea EN LA LLAMADA a la función y NO en su definición. Por eso, si llamas 100 veces a la función &lt;code&gt;local_scope&lt;/code&gt;, tendrás 100 scopes diferentes. Esto es así incluso si haces llamadas recursivas.&lt;/p&gt;

&lt;p&gt;Otra cosa importante es que, cuando tú defines una variable en la cabecera de una función, esa variable &lt;strong&gt;ya existirá&lt;/strong&gt; en el scope de esa función. O lo que es lo mismo, ya está definida y puedes usarla en el scope local de esa función todo lo que necesites.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scope local
&lt;/h3&gt;

&lt;p&gt;Es el que acabas de ver. Equivalente a una habitación. Defines una función (lambda o normal), y ahí tienes tu scope. Todo lo que definas en la cabecera o en el cuerpo de la función formará parte de tu scope local.&lt;/p&gt;

&lt;h3&gt;
  
  
  Envoltura
&lt;/h3&gt;

&lt;p&gt;Esto no es más que un scope dentro de un scope. Lo mismo que pasaba con el baño en el cuarto de Homer y Marge. Para hacer esto, lo único que tienes que hacer es crear un scope dentro de otro. Por ejemplo, anidando funciones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enclosing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_out&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;other_var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HI"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enclosed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_in&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other_var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;enclosed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos a ver los scopes de este código de una manera un poco más gráfica:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8JAvWuzm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mriwxb3gylylv4wpx8pf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8JAvWuzm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mriwxb3gylylv4wpx8pf.png" alt="Código con scopes superpuestos" width="474" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La función &lt;code&gt;enclosing&lt;/code&gt; estaría definiendo el scope naranja y la &lt;code&gt;enclosed&lt;/code&gt; un scope dentro del anterior.&lt;/p&gt;

&lt;p&gt;Por lo tanto, si ejecutamos ese código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; function_in = enclosing("Out") 
&amp;gt;&amp;gt;&amp;gt; function_in("In") 
HI
Out
In
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pero sin embargo, si intentamos acceder directamente a la función interna:&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;&amp;gt;&amp;gt;&lt;/span&gt; enclosed&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"In"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
Traceback &lt;span class="o"&gt;(&lt;/span&gt;most recent call last&lt;span class="o"&gt;)&lt;/span&gt;:
  File &lt;span class="s2"&gt;"&amp;lt;stdin&amp;gt;"&lt;/span&gt;, line 1, &lt;span class="k"&gt;in&lt;/span&gt; &amp;lt;module&amp;gt;
NameError: name &lt;span class="s1"&gt;'enclosed'&lt;/span&gt; is not defined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se queja porque no podemos entrar en habitaciones, solo salir de ellas!&lt;/p&gt;

&lt;h3&gt;
  
  
  Global
&lt;/h3&gt;

&lt;p&gt;El scope global sería el pasillo. Es un scope que está disponible para todos, es el mas general y también se le llama scope de módulo (module scope). Es el scope general que tienes en tu archivo de Python. Un ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;super_global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy fuera de todo"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;super_global&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function_enclosing&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function_enclosed&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;super_global&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;my_function_enclosed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(super_global)
Estoy fuera de todo
&amp;gt;&amp;gt;&amp;gt; my_function()
Estoy fuera de todo
&amp;gt;&amp;gt;&amp;gt; my_function_enclosing()
Estoy fuera de todo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Todas tienen acceso a la variable &lt;code&gt;super_global&lt;/code&gt; porque sólo tienen que salir de habitaciones para ir a buscarla.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incorporado (Built-in)
&lt;/h3&gt;

&lt;p&gt;Este es un scope especial, es un scope en el que hay cosas que vienen por defecto con python y que no es necesario declarar, importar ni nada. Un ejemplo de lo que hay en este scope son las funciones &lt;code&gt;len&lt;/code&gt;, &lt;code&gt;sorted&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;...&lt;/p&gt;

&lt;p&gt;Por eso podemos hacer cosas como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;lst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sin necesidad de definir ni importar &lt;code&gt;len&lt;/code&gt; en ninguna parte.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo podemos añadir elementos a un scope?
&lt;/h3&gt;

&lt;p&gt;Hay varias maneras de hacer esto. La primera y la más evidente es declarando una nueva variable. Al hacer &lt;code&gt;my_var = "Hola"&lt;/code&gt; estás añadiendo una nueva variable &lt;code&gt;my_var&lt;/code&gt; a tu scope.&lt;/p&gt;

&lt;p&gt;Otra manera es usar un &lt;code&gt;import&lt;/code&gt;. Cuando tú haces &lt;code&gt;import math&lt;/code&gt; estás trayendo todo lo que haya en el scope global del módulo &lt;code&gt;math&lt;/code&gt; a tu scope. Por eso puedes usar funciones como &lt;code&gt;sqrt&lt;/code&gt; en tu scope solo si importas primero &lt;code&gt;math&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por último, me gustaría remarcar que la única forma de declarar una nueva variable en un scope no es con la forma &lt;code&gt;var = "algo"&lt;/code&gt;. Cuando haces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estás añadiendo la variable &lt;code&gt;param&lt;/code&gt; al scope de la función &lt;code&gt;func&lt;/code&gt; aunque no estés asignándola a nada en ese momento. En el momento de la llamada se creará un scope para esa función y esa variable se creará automáticamente en el scope con el valor que haya recibido el parámetro.&lt;/p&gt;

&lt;p&gt;Un último apunte es que al hacer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;También estás añadiendo la variable &lt;code&gt;number&lt;/code&gt; a scope global (si el &lt;code&gt;for&lt;/code&gt; lo tienes dentro de una función, lo añadirías a esa función).&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Y qué leches es eso del shadowing?
&lt;/h3&gt;

&lt;p&gt;El &lt;em&gt;shadowing&lt;/em&gt; no es más que "eclipsar" una variable de un scope externo con una variable de un scope interno. Vamos a verlo con un ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Soy globalísima"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;modify&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Soy localísima"&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Párate un minuto y piensa qué debería imprimir ese código...&lt;/p&gt;

&lt;p&gt;Te pongo la respuesta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(var)
Soy globalísima
&amp;gt;&amp;gt;&amp;gt; modify()
Soy localísima
&amp;gt;&amp;gt;&amp;gt; print(var)
Soy globalísima
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un momento, un momento... ¿no debería aparecer "Soy localísima" dos veces? Porque estoy modificando la variable del scope global en la función, ¿cierto?&lt;/p&gt;

&lt;p&gt;Lo cierto es que no. Lo que estoy haciendo es &lt;strong&gt;definir&lt;/strong&gt; una variable nueva en el scope local que eclipsa (hace &lt;em&gt;shadowing&lt;/em&gt;) a la del scope global.&lt;/p&gt;

&lt;p&gt;De la misma manera, con scopes de envoltura, si hago esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;outter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy fuerísima"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy dentro del tó"&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ejecuto esa función, habrá un comportamiento similar al anterior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; outter()
Estoy fuerísima
Estoy dentro del tó
Estoy fuerísima
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al re-asignar la variable &lt;code&gt;var&lt;/code&gt; en la función &lt;code&gt;inner&lt;/code&gt;, lo que estoy haciendo es declarar una variable nueva que hace &lt;code&gt;shadowing&lt;/code&gt; a la externa.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Pero todo esto no iba de una lambda?
&lt;/h2&gt;

&lt;p&gt;Pues sí!! Y ahora puedes entender perfectamente por qué pasaba aquello en nuestro código. Vamos a volver al código inicial:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;potencias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;potencias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;potencias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Según nuestra intuición eso debería dar 16, pero da 65535. Vamos a analizar el código con los conocimientos que tenemos ahora.&lt;/p&gt;

&lt;p&gt;Sabes que tenemos un scope global que envuelve a todo el código.&lt;/p&gt;

&lt;p&gt;Además sabes que una lambda, como buena función, crea otro scope.&lt;/p&gt;

&lt;p&gt;Pero sabes una cosa más... Que los scopes de una función se crean &lt;strong&gt;en el momento de su llamada&lt;/strong&gt; y no en su definición.&lt;/p&gt;

&lt;p&gt;Eso significa que, cuando creas la primera lambda, el &lt;code&gt;number&lt;/code&gt; que tiene como exponente será 2, en la segunda lambda será 4 y en la tercera 16.&lt;/p&gt;

&lt;p&gt;Pero una vez que termina el bucle, &lt;code&gt;number&lt;/code&gt; permanece definido como 16, pues es el último valor de la lista. Entonces cuando llamas a &lt;code&gt;potencias[2]&lt;/code&gt; se llama la primera lambda, &lt;strong&gt;en ese momento&lt;/strong&gt; se crea un scope, y se busca number en el scope superior (el global) y, como es 16, al hacer &lt;code&gt;potencias[2](4)&lt;/code&gt; estamos haciendo 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;16416^4&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, que es nada más y nada menos que nuestro resultado, 65535.&lt;/p&gt;
&lt;h3&gt;
  
  
  ¿Cómo solucionarlo?
&lt;/h3&gt;

&lt;p&gt;Sabes que necesitas que &lt;code&gt;number&lt;/code&gt;, el exponente, quede &lt;strong&gt;definida&lt;/strong&gt; en el scope de la lambda en el momento de la creación, en vez de acceder a la del scope global.&lt;/p&gt;

&lt;p&gt;Para eso sanes que si defines esa variable como argumento de la lambda y la igualamos a la superior, esa variable quedará definida y fijada con ese valor al crearla, incluso si la llamamos igual (por el shadowing).&lt;/p&gt;

&lt;p&gt;Si cambias el código a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;potencias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;potencias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;potencias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estás definiendo una variable &lt;code&gt;number&lt;/code&gt; dentro de ese scope, que tomará por defecto el valor que tenga la variable del bucle homónima en ese momento. Por eso cuando llames a &lt;code&gt;potencias[2](4)&lt;/code&gt;, se creará un scope para esa función, pero con la variable number prefijada al valor que tenía en el momento de la creación de la lambda, pues ese valor por defecto es fijo.&lt;/p&gt;

&lt;p&gt;Ahora sí, el resultado de esa ejecución es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;potencias&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cómo modificar el scope
&lt;/h2&gt;

&lt;p&gt;Hay un par de opciones para modificar el scope de Python y, aunque útiles, debemos tratarlas con mucho cuidado.&lt;/p&gt;

&lt;p&gt;Imagina que tienes, como en el ejemplo del shadowing, este código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Soy globalísima"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;modify&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Soy localísima"&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y tú necesitas irremediablemente modificar la variable &lt;code&gt;var&lt;/code&gt; dentro de la función. Hay una forma de modificar el scope de esa función para que esa variable se "enlace" bidireccionalmente con la del scope global.&lt;/p&gt;

&lt;p&gt;Esto significa que tanto si la lees como si la modificas estarás modificando la del global. Para esto se usa la palabra &lt;code&gt;global&lt;/code&gt; seguida del nombre de la variable que queremos enlazar con una global. Si bien vimos que el código anterior devolvía:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(var)
Soy globalísima
&amp;gt;&amp;gt;&amp;gt; modify()
Soy localísima
&amp;gt;&amp;gt;&amp;gt; print(var)
Soy globalísima
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al cambiar el código a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Soy globalísima"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;modify&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Soy localísima"&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado de ejecutarlo nuevamente será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(var)
Soy globalísima
&amp;gt;&amp;gt;&amp;gt; modify()
Soy localísima
&amp;gt;&amp;gt;&amp;gt; print(var)
Soy localísima
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hemos modificado la variable global satisfactoriamente!&lt;/p&gt;

&lt;p&gt;Ahora imagina, por otro lado, el siguiente código que vimos también en el shadowing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;outter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy fuerísima"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy dentro del tó"&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y, de nuevo, necesitas irremediablemente modificar la variable &lt;code&gt;var&lt;/code&gt; dentro de la función &lt;code&gt;inner&lt;/code&gt;. En este caso &lt;code&gt;global&lt;/code&gt; no nos sirve, pues estaríamos enlazando &lt;code&gt;var&lt;/code&gt; a una variable del scope global llamada &lt;code&gt;var&lt;/code&gt;, que no existe. Si intentamos hacer esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;outter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy fuerísima"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy dentro del tó"&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; outter()
Estoy fuerísima
Estoy dentro del tó
Estoy fuerísima
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Que es lo mismo que antes, solo que ahora en el scope global, tendremos una variable &lt;code&gt;var&lt;/code&gt; con el valor "Estoy dentro del tó", que no es lo que queremos.&lt;/p&gt;

&lt;p&gt;En este caso python nos ofrece otra palabra que se usa exactamente igual que la anterior y es &lt;code&gt;nonlocal&lt;/code&gt;. Esto lo que hace es buscar la variable etiquetada como &lt;code&gt;nonlocal&lt;/code&gt; en el scope superior (y en el superior de ese, y así sucesivamente) y enlazarla de manera bidireccional igual que se hacía con global. Por tanto, si cambiamos el código a:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;outter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy fuerísima"&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;nonlocal&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Estoy dentro del tó"&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estaremos enlazando la variable &lt;code&gt;var&lt;/code&gt; de inner, con la variable &lt;code&gt;var&lt;/code&gt; de outter y el resultado será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; outter()
Estoy fuerísima
Estoy dentro del tó
Estoy dentro del tó
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora sí, una modificación de la variable exterior desde la función interior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importante&lt;/strong&gt;: &lt;code&gt;nonlocal&lt;/code&gt; busca en los scopes superiores de manera sucesiva hasta llegar al global. Si cuando llega al global no ha encontrado esa variable, dará un error. &lt;code&gt;nonlocal&lt;/code&gt; no permite enlazar una variable interna con una global, para eso tenemos la palabra &lt;code&gt;global&lt;/code&gt;. Un ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hola"&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;nonlocal&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Adios"&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  File "&amp;lt;stdin&amp;gt;", line 3
SyntaxError: no binding for nonlocal 'var' found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dice que no hay ninguna variable &lt;code&gt;var&lt;/code&gt; a la que enlazar. Sin embargo al cambiar por &lt;code&gt;global&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hola"&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;
    &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Adios"&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El código funciona sin problemas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Algunas curiosidades de Python
&lt;/h2&gt;

&lt;h3&gt;
  
  
  El scope en los bucles
&lt;/h3&gt;

&lt;p&gt;Ni un bucle &lt;code&gt;for&lt;/code&gt; ni un bucle &lt;code&gt;while&lt;/code&gt; definen un nuevo scope. Por tanto, cualquier variable que definas dentro de ellos seguirá viva fuera del bucle. Incluso la variable que definas en el bucle en sí!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado de esa ejecución será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
1
2
3
4
&amp;gt;&amp;gt;&amp;gt; print(number)
4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La variable &lt;code&gt;number&lt;/code&gt; sigue existiendo incluso después del bucle.&lt;/p&gt;

&lt;h3&gt;
  
  
  El scope en los bloques if
&lt;/h3&gt;

&lt;p&gt;Pasa exactamente igual que en los bucles, toda variable que definas dentro de un bloque if, estará disponible después.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hola"&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado será:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hola
Hola
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Algo muy similar a lo que pasaba en el anterior caso.&lt;/p&gt;

&lt;h3&gt;
  
  
  El scope de los list/dict comprehension
&lt;/h3&gt;

&lt;p&gt;Sin embargo, en los list comprehension el scope se comporta ligeramente distinto. Al ejecutar el código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si luego intentamos acceder a &lt;code&gt;number&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; [number for number in range(5)]
[0, 1, 2, 3, 4]
&amp;gt;&amp;gt;&amp;gt; number
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
NameError: name 'number' is not defined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Porque en un list/dict comprehension, las variables no se crean en el scope en el que estén, sino que solo existen durante el comprehesion concreto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scope en un try/except
&lt;/h3&gt;

&lt;p&gt;Cuando tenemos un bloque &lt;code&gt;try/except&lt;/code&gt; podemos pensar que se van a comportar igual que un &lt;code&gt;if&lt;/code&gt;, pero hay una particularidad. Imagina el siguiente código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si intentamos acceder a &lt;code&gt;a&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; a
1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La tenemos disponible en el scope sin problema. Pero ahora mira este código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si ahora intentamos acceder a &lt;code&gt;e&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; e
Traceback (most recent call last):
  File "&amp;lt;stdin&amp;gt;", line 1, in &amp;lt;module&amp;gt;
NameError: name 'e' is not defined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La variable &lt;code&gt;e&lt;/code&gt;, aunque se define en el except y se entra por ahí, no se crea en el scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;Pues básicamente has entendido cómo funcionan los scopes en Python, cómo puedes usarlos a tu favor y qué cosas debes tener en cuenta.&lt;/p&gt;

&lt;p&gt;Además, has aprendido qué estructuras crean scopes en Python, cómo traer variables nuevas a tu scope e incluso cómo modificar el comportamiento de los scopes en Python con &lt;code&gt;global&lt;/code&gt; y &lt;code&gt;nonlocal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para cualquier duda que tengas te leo en los comentarios y, para aprender cosas como estas y &lt;strong&gt;mucho&lt;/strong&gt; más molonas, no dejes de mirar los cursos de &lt;a href="https://www.corecode.school/bootcamp/big-data-machine-learning"&gt;Core Scool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nos vemos en el próximo post!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Implementing key objects in Unity by a newbie. Part 2.</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Sun, 16 May 2021 07:45:50 +0000</pubDate>
      <link>https://dev.to/alesanchez/implementing-key-objects-in-unity-by-a-newbie-part-2-h59</link>
      <guid>https://dev.to/alesanchez/implementing-key-objects-in-unity-by-a-newbie-part-2-h59</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/alesanchez/implementing-key-objects-in-unity-by-a-newbie-part-1-1hhi"&gt;previous part&lt;/a&gt; we built the foundations for implementing the key objects.&lt;/p&gt;

&lt;p&gt;In this post we are going to finish that task developing the actionable by key specific object and testing everything we developed until now.&lt;/p&gt;

&lt;p&gt;In the first part the last step was the 3, so here we will start directly in the 4, for preserving the tags in the repo :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Actionable by key
&lt;/h2&gt;

&lt;p&gt;Let's implement the &lt;strong&gt;key&lt;/strong&gt; (sorry for that) part of the post! Our ActionableByKey class!&lt;/p&gt;

&lt;p&gt;As we saw in the diagram, the &lt;code&gt;ActionableByKey&lt;/code&gt; object used a feature called events! Events in C# are a way to notify that something happened. We are going to use that to send a message to the universe when an item has been picked. Start by defining the event we'll need.&lt;/p&gt;

&lt;p&gt;Create a new folder called "Events" inside the "Scripts" one and put inside a file called "ItemPick":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;NotifyItemPick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ActionableObject&lt;/span&gt; &lt;span class="n"&gt;pickedItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ItemPickEvents&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;NotifyItemPick&lt;/span&gt; &lt;span class="n"&gt;OnItemPick&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;NotifyItemPick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ActionableObject&lt;/span&gt; &lt;span class="n"&gt;pickedItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;OnItemPick&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pickedItem&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;First we define a &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/"&gt;deletage&lt;/a&gt; called &lt;code&gt;NotifyItemPick&lt;/code&gt; that will be called with an &lt;code&gt;ActionableObject&lt;/code&gt; referencing the picked item.&lt;/p&gt;

&lt;p&gt;The class itself will contain the &lt;code&gt;OnItemPick&lt;/code&gt; event as static, so anyone can subscribe to it and a static method for notifying an item pick.&lt;/p&gt;

&lt;p&gt;We have talked a lot about picking an item and objects that will be interacted when an item is picked, but haven't defined the item itself yet!&lt;/p&gt;

&lt;p&gt;In order to represent our item, we need a &lt;code&gt;KeyItem&lt;/code&gt; script that will define an object that has to be picked to activate another. Picking an object is some sort of interaction so... we can take advantage of our generic actionable object! Create a new folder called "Items" inside "Scripts" and, inside, create a "KeyItem" file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KeyItem&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ActionableObject&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InnerStart&lt;/span&gt;&lt;span class="p"&gt;(){}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InnerInteract&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ItemPickEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotifyItemPick&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="nf"&gt;Destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameObject&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;As you can see, the inner start does nothing and the interaction just notify that itself has been picked, followed by the descruction of the picked item. Easy!&lt;/p&gt;

&lt;p&gt;Now that we have the events as well as the key item, the next step is to create the actionable by key one. Create a file side by side with &lt;code&gt;StandardActionableObject&lt;/code&gt; and call it &lt;code&gt;ActionableByKey&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActionableByKey&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StandardActionableObject&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Tooltip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This item will activate the actuator of this object when picked"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;KeyItem&lt;/span&gt; &lt;span class="n"&gt;actionedBy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InnerStart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InnerStart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;SetIsInteractive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&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;void&lt;/span&gt; &lt;span class="nf"&gt;OnEnable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ItemPickEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnItemPick&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnItemPick&lt;/span&gt;&lt;span class="p"&gt;;&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;void&lt;/span&gt; &lt;span class="nf"&gt;OnDisable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ItemPickEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnItemPick&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;OnItemPick&lt;/span&gt;&lt;span class="p"&gt;;&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;void&lt;/span&gt; &lt;span class="nf"&gt;OnItemPick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ActionableObject&lt;/span&gt; &lt;span class="n"&gt;pickedItem&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="n"&gt;pickedItem&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;KeyItem&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;pickedItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actionedBy&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;SetIsInteractive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first attribute is a reference to the key item that need to be picked to activate this object.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;InnerStart&lt;/code&gt; deactivates the interactions with this object.&lt;/p&gt;

&lt;p&gt;We will subscribe to the &lt;code&gt;OnItemPick&lt;/code&gt; event in the &lt;code&gt;OnEnable&lt;/code&gt; and unsusbcribe in the &lt;code&gt;OnDisable&lt;/code&gt;. The function bound to the event is called also &lt;code&gt;OnItemPick&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;OnItemPick&lt;/code&gt; method we check if the picked item is a KeyItem as well as the one that activates the interactions with the actionable object. If both conditions are met, activate the interactions :D&lt;/p&gt;

&lt;p&gt;We are almost there! Just one more thing to code and we can jump back to the Unity editor!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Access the code for this step &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors/tree/step-4"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 5: How to interact with objects
&lt;/h2&gt;

&lt;p&gt;Ok, we have set everything up so that when we interact with an object it works like a charm but... How can we interact with an object?&lt;/p&gt;

&lt;p&gt;That is what we are going to solve here. In general terms, the approach is to throw &lt;a href="https://docs.unity3d.com/ScriptReference/Physics.Raycast.html"&gt;Raycast&lt;/a&gt; from the player eyes (more or less), a unit of distance and a half away and check if it collides with a collider belonging to an &lt;code&gt;IActionableObject&lt;/code&gt; GameObject (that's why we set a collider up in our door). If we find an actionable object, we will store a reference to it and show the interaction text. When the key for interacting is pressed, we will call the &lt;code&gt;Interact&lt;/code&gt; function of the stored actionable object.&lt;/p&gt;

&lt;p&gt;We will create a file called &lt;code&gt;ObjectInteractuator&lt;/code&gt; inside the &lt;code&gt;Scripts&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ObjectInteractuator&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;InteractionText&lt;/span&gt; &lt;span class="n"&gt;interactText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;LayerMask&lt;/span&gt; &lt;span class="n"&gt;interactionMask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;GameActions&lt;/span&gt; &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Camera&lt;/span&gt; &lt;span class="n"&gt;mainCamera&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;IActionableObject&lt;/span&gt; &lt;span class="n"&gt;currInteractiveObject&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;void&lt;/span&gt; &lt;span class="nf"&gt;Awake&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GameActions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;performed&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnInteractPerformed&lt;/span&gt;&lt;span class="p"&gt;;&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;void&lt;/span&gt; &lt;span class="nf"&gt;OnEnable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enable&lt;/span&gt;&lt;span class="p"&gt;();&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;void&lt;/span&gt; &lt;span class="nf"&gt;OnDisable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Disable&lt;/span&gt;&lt;span class="p"&gt;();&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;void&lt;/span&gt; &lt;span class="nf"&gt;OnDestroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;performed&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;OnInteractPerformed&lt;/span&gt;&lt;span class="p"&gt;;&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;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mainCamera&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Update is called once per frame&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;CheckInteractions&lt;/span&gt;&lt;span class="p"&gt;();&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;void&lt;/span&gt; &lt;span class="nf"&gt;CheckInteractions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Ray&lt;/span&gt; &lt;span class="n"&gt;cameraRay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mainCamera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ViewportPointToRay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Vector3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;2f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;RaycastHit&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;IActionableObject&lt;/span&gt; &lt;span class="n"&gt;objectHit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// We are looking towards an interactive object an in range&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Physics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Raycast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cameraRay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1.5f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interactionMask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QueryTriggerInteraction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collide&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TryGetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionableObject&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;objectHit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;objectHit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsInteracterActive&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="n"&gt;interactText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetInteractionText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objectHit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetInteractionText&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="n"&gt;currInteractiveObject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;objectHit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;interactText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interactText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;interactText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Disable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;currInteractiveObject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&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="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnInteractPerformed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CallbackContext&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;currInteractiveObject&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;Interact&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 first attribute is a reference to the &lt;code&gt;InteractionText&lt;/code&gt; of the scene (we will create it later). The second is the interaction mask the raycast has to check for performing a hit (you can create a custom layer if you want, but in this example we will use the &lt;code&gt;default&lt;/code&gt; one).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;GameActions&lt;/code&gt; are needed to listen for event sent when the interaction key is pressed. Finally, we need the &lt;code&gt;Camera&lt;/code&gt; to cast the ray from it.&lt;/p&gt;

&lt;p&gt;The last attribute is to store a reference to the current interactive object (the one we are looking at right now, if any).&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Awake&lt;/code&gt; we will bind the &lt;code&gt;OnInteractPerformed&lt;/code&gt; function to the &lt;code&gt;Interact&lt;/code&gt; action, and will unbind it in the &lt;code&gt;OnDestroy&lt;/code&gt; function. The only purpose of that function is to call the &lt;code&gt;Interact&lt;/code&gt; method of the interactive object we are looking at right now (checking first if there is any).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;OnEnable&lt;/code&gt; and &lt;code&gt;OnDisable&lt;/code&gt; functions are used to enable and disable the game actions.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Start&lt;/code&gt; we are storing the reference to the main camera and in the &lt;code&gt;Update&lt;/code&gt; we are going to check for interactions.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CheckInteractions&lt;/code&gt; is where the magic happens, let's look into it step by step.&lt;/p&gt;

&lt;p&gt;First we construct a Ray that starts at the middle point of the viewport (that's why we use &lt;code&gt;Vector.One / 2f&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Then we create two variables to store the hit of the raycast as well as the actionable object.&lt;/p&gt;

&lt;p&gt;Then we have an if with three conditions. The first one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Physics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Raycast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cameraRay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1.5f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interactionMask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QueryTriggerInteraction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Collide&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This casts the previously created ray 1.5 units of distance away, storing the possible hit in the &lt;code&gt;hit&lt;/code&gt; variable, colliding only with &lt;code&gt;interactionMask&lt;/code&gt; and reporting with trigger colliders thanks to the &lt;code&gt;QueryTriggerInteraction.Collide&lt;/code&gt; attribute. If that condition is met (an object has been hit), then it goes for the second one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TryGetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionableObject&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;objectHit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one asks if the collided object has a component implementing the interface &lt;code&gt;IActionableObject&lt;/code&gt;. If so, it stores the found component in the &lt;code&gt;objectHit&lt;/code&gt; variable and goes for the last check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;objectHit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsInteracterActive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one just asks if the interactions are enabled for the collided object.&lt;/p&gt;

&lt;p&gt;If all of that is met, we set the interaction text to the one returned by the collided object, store a reference to the collided object and enable the interact text component.&lt;/p&gt;

&lt;p&gt;If any of the conditions fail it means that we are not looking to an interactive object, so we disable the interaction text and clear the reference.&lt;/p&gt;

&lt;p&gt;And with that, we have all set for interacting with objects!! Let's move again to the editor for the final touches.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Access the code for this step &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors/tree/step-5"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 6: Attaching all needed scripts
&lt;/h2&gt;

&lt;p&gt;Now it's time to start adding scripts to all of the GameObjects in the scene.&lt;/p&gt;

&lt;p&gt;As we said earlier, we must create the elements needed for showing the interaction text. We are going to use an overlay canvas with a text. That text will be white so that it makes more contrast with the background.&lt;/p&gt;

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

&lt;p&gt;After creating the canvas and switching the EventSystem to the new input system, we must attach the &lt;code&gt;InteractionText&lt;/code&gt; script to the Text component in order to reference it in the &lt;code&gt;ObjectInteractuator&lt;/code&gt; script.&lt;/p&gt;

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

&lt;p&gt;To set up the interactor, we need to attach the &lt;code&gt;ObjectInteractuator&lt;/code&gt; script to the FPSController. Then reference the text component we created in the previous step and set the interaction mask to &lt;strong&gt;Default&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The last step before we can begin to interact with our door is to make it a &lt;code&gt;StandardActionableObject&lt;/code&gt; (for the moment).&lt;/p&gt;

&lt;p&gt;Before that, we must fix a thing we forgot when creating the animation in Part 1. We need to make sure that the animation is not played on loop. For that, go to the animation file and uncheck the "Loop time" attribute. Then we just need to attach the &lt;code&gt;StandardActionableObject&lt;/code&gt; script to it and fill the animation state name, which is "DoorOpen". &lt;/p&gt;

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

&lt;p&gt;Now we are able to play around with our door opening and closing it. Our very last step is to make it actionable by a key!!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Access the code developed in this step &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors/tree/step-6"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: I changed the colliders of the doors so the player can walk across it. I created one trigger collider around the whole door for the raycast and one collider in the door itself to prevent the player from crossing it when closed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 7: Making the door actionable by &lt;del&gt;cube&lt;/del&gt; key
&lt;/h2&gt;

&lt;p&gt;The last thing we need to finish our heroic journey is making the door interactive only when a specific item is picked. In a real game, that item would be a key, in our amazing AAA game, it will be the most cubic cube you'll ever see.&lt;/p&gt;

&lt;p&gt;The first step is to place our cube and make it a KeyItem. Since it will be picked up and destroyed, we don't need any reverse interaction text.&lt;/p&gt;

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

&lt;p&gt;And the last thing... Replace the script attached to the door with an &lt;code&gt;ActionableByKey&lt;/code&gt; script and set the reference to our key. That's all! The door won't be interactive until we pick up the key!&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Access the code of this step &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors/tree/step-7"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclussions... or something like that
&lt;/h2&gt;

&lt;p&gt;So... yes... it's finished, it's working, it's awesome... I'm not crying, you're crying.&lt;/p&gt;

&lt;p&gt;Now seriously, I hope you enjoyed the journey reading and following the steps as much as I enjoyed writing the posts and recording the videos.&lt;/p&gt;

&lt;p&gt;As in the first part, feel free to make any suggestions, improvements, doubts, requests or whatever you want to say!&lt;/p&gt;

&lt;p&gt;See you in the next post!&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Implementing key objects in Unity by a newbie. Part 1.</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Wed, 12 May 2021 15:45:43 +0000</pubDate>
      <link>https://dev.to/alesanchez/implementing-key-objects-in-unity-by-a-newbie-part-1-1hhi</link>
      <guid>https://dev.to/alesanchez/implementing-key-objects-in-unity-by-a-newbie-part-1-1hhi</guid>
      <description>&lt;p&gt;Hello everyone once again! Today I’m writing a post about Unity! I started developing using Unity just a few months ago, but despite having some experience in development, this is my first time with videogames.&lt;/p&gt;

&lt;p&gt;I believe that explaining each step while having zero experience myself might be interesting and could provide other developers with some insight of the challenges that come with developing games.&lt;/p&gt;

&lt;p&gt;I’m a newbie when it comes to developing videogames in general, and more particularly using Unity, so feel free to make any suggestions you might have, and also let me know if you believe there are more standardized ways to solve the problems I’m about to propose.&lt;/p&gt;

&lt;p&gt;As a final note before we dive in, I would like to remind you that I’m no artist at all, therefore I won’t be creating any assets for the game from scratch (like 3D models, textures, animations and so on). I’ll be using free asset packs from the unity store :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0 - Preparing the basic environment.
&lt;/h2&gt;

&lt;p&gt;Everything being developed in this post is publicly available in &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors" rel="noopener noreferrer"&gt;this repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Every step is going to be also accessible via Tags. For example, you can check the final code of step 0 &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors/tree/step-0" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this first part we are only setting up the minimum things we need to start working. This includes a first person player controller that was also implemented by me (not covered in this post). A ground plane with a wood tiling downloaded from the Assets Store (this &lt;a href="https://assetstore.unity.com/packages/2d/textures-materials/wood/wooden-floor-materials-150564" rel="noopener noreferrer"&gt;package&lt;/a&gt;) and a door also downloaded from the assets store (this &lt;a href="https://assetstore.unity.com/packages/3d/props/apartment-door-146225" rel="noopener noreferrer"&gt;package&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That door is the one we are going to animate later for opening and closing it.&lt;/p&gt;

&lt;p&gt;For the character movement I've set up the new input system so we can move with the standard WASD keys.&lt;/p&gt;

&lt;p&gt;Feel free to check out the project and explore everything in there until you feel comfortable to move to the next step.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: For showing the cursor while playing the game, press &lt;strong&gt;ESC&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 1 - Animating the door
&lt;/h2&gt;

&lt;p&gt;In this step we are going to animate the door so it can be opened and closed. For that we are going to make the door rotate around the hinges, by rotating the &lt;em&gt;SimpleDoor:Global_ControlSimpleDoor_MainDoor_LOD1&lt;/em&gt; component around the Y axis.&lt;/p&gt;

&lt;p&gt;First things first: If you haven’t done it already, make sure to display the animation window by clicking Window &amp;gt; Animation &amp;gt; Animation. Then switch to that tab, click the door and, in the Animation tab, click to create a new animation. Call it "Door".&lt;/p&gt;

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

&lt;p&gt;Once we have the animation file, we are going to create the animation itself. Switch to the Animation tab and click the &lt;em&gt;SimpleDoor:Global_ControlSimpleDoor_MainDoor_LOD1&lt;/em&gt; component inside &lt;em&gt;Aparment_Door&lt;/em&gt; prefab.&lt;/p&gt;

&lt;p&gt;Now click the record button in the Animation tab and right click the &lt;em&gt;Rotation&lt;/em&gt; attribute inside Transform section of &lt;em&gt;SimpleDoor:Global_ControlSimpleDoor_MainDoor_LOD1&lt;/em&gt; and click &lt;em&gt;Add Key&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That will create a &lt;a href="https://docs.unity3d.com/Manual/animeditor-AnimatingAGameObject.html" rel="noopener noreferrer"&gt;key frame&lt;/a&gt; in the frame 0 with the rotation set to (0,0,0). Then move to the frame 120 and change the rotation around the Y axis to 97º. It's important to change it in the rotation section instead of rotating directly in the scene view.&lt;/p&gt;

&lt;p&gt;Now you should have 2 key frames, so you can stop recording and save the animation.&lt;/p&gt;

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

&lt;p&gt;Now that we have the animation ready we have to set the animation controller up so we can control when to play the animation and how.&lt;/p&gt;

&lt;p&gt;Show the animator tab by clicking Window &amp;gt; Animation &amp;gt; Animator and click the &lt;em&gt;Aparment_Door&lt;/em&gt; prefab so you can manipulate the animation state machine of the door.&lt;/p&gt;

&lt;p&gt;We are going to create a new state and call it &lt;em&gt;Idle&lt;/em&gt;. Then make the layer default one and uncheck the "Write Defaults" checkbox.&lt;/p&gt;

&lt;p&gt;Next step is create a transition from the &lt;em&gt;Idle&lt;/em&gt; state to the already existing &lt;em&gt;Door&lt;/em&gt; state and uncheck the "Has Exit Time" checkbox from the transition. Also uncheck the "Write Defaults" checkbox from the &lt;em&gt;Door&lt;/em&gt; state.&lt;/p&gt;

&lt;p&gt;Finally, the last steps we need to follow are to change the door state name to &lt;em&gt;DoorOpen&lt;/em&gt;, and create a new Float parameter which we will call &lt;em&gt;direction&lt;/em&gt;. That param will be used to control whether the animation has to be played regularly or backwards. To make that happen we must go to the &lt;em&gt;DoorOpen&lt;/em&gt; state and under &lt;em&gt;Speed&lt;/em&gt; parameter there will be a greyed &lt;em&gt;Multiplier&lt;/em&gt; parameter. That is what is going to allow us to reverse the animation, so check the "parameter" checkbox and the drop down should show the "direction" parameter we created earlier.&lt;/p&gt;

&lt;p&gt;To check that everything is working fine we have to play the game and check that the &lt;em&gt;Idle&lt;/em&gt; state is played on loop.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Access all the step changes &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors/tree/step-1" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 2 - Making generic actionable objects
&lt;/h2&gt;

&lt;p&gt;Now it's time to code!&lt;/p&gt;

&lt;p&gt;We are going to start creating a generic type for defining actionable objects. Since we are going to implement not only standard actionable objects but also actionable by key or by trigger (in upcoming posts), we'll create the foundations first.&lt;/p&gt;

&lt;p&gt;We are going to use inheritance for that. If you don't know what inheritance is, is a technique that allows us to reuse and extend functionality by using parent-child classes. For a more extended a technical definition, head to &lt;a href="https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)" rel="noopener noreferrer"&gt;someone who knows more than me&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9s610c3xcl11t61enia4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9s610c3xcl11t61enia4.jpg" alt="Diagram showing inheritance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will see each part in detail when we reach them. We are going to define an interface to make our life easier when it comes to detect an actionable object and also a specific class for each type of actionable object, extending the generic classes with specific functionality. And for the key objects specifically, we will take advantage of the &lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/events/" rel="noopener noreferrer"&gt;C# events&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Start creating the following folder structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├───Scripts
│   ├───ActionableObjects
│   │   └───Generics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of the files created in this section are going to be placed inside the &lt;code&gt;Generics&lt;/code&gt; folder.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the interface
&lt;/h3&gt;

&lt;p&gt;Our interface is an easy one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IActionableObject&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Interact&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetInteractionText&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsInteracterActive&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;We have to define an &lt;code&gt;Interact&lt;/code&gt; method which will be called when the actionable object is interacted and will trigger whatever behavior we want.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GetInteractionText&lt;/code&gt; returns the text to show when looking at the object (if any). For example: "Press A to open".&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IsInteracterActive&lt;/code&gt; is for telling us if the object is interactive or not (for a key object, it will return false until the key is picked up).&lt;/p&gt;

&lt;h3&gt;
  
  
  ActionableObject and InteractionText
&lt;/h3&gt;

&lt;p&gt;Now that our interface is ready to be used to detect actionable objects, let's move to our other two generic components. First the InteractionText:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;RequireComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InteractionText&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="n"&gt;m_text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;m_initialText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;m_interactionText&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;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m_text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

        &lt;span class="n"&gt;m_initialText&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&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;void&lt;/span&gt; &lt;span class="nf"&gt;Update&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="n"&gt;m_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;m_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m_initialText&lt;/span&gt;&lt;span class="p"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;m_interactionText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&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;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SetInteractionText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;interactionText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m_interactionText&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;interactionText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&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;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Disable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsEnabled&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&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 first thing we are going to do in this code is to forcefully bound the script to a GameObject with a Text component.&lt;/p&gt;

&lt;p&gt;The class will have a referente to the &lt;code&gt;Text&lt;/code&gt; component and two attributes for holding the initial text and the interaction text.&lt;/p&gt;

&lt;p&gt;We are going to use the &lt;code&gt;Start&lt;/code&gt; method to store the reference to the text component and setting the &lt;code&gt;m_initialText&lt;/code&gt; to the text inside the component.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Update&lt;/code&gt; we are just setting the text of the component to a combination of the initial text and the interaction text. With that, we can add a common starting text to all interaction texts if needed. For example prepending "Press X to" to every interaction text.&lt;/p&gt;

&lt;p&gt;The last thing is a function for changing the interaction text.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: We could enhance the performance by having a flag indicating when the interaction text has changed and only updating it when changed, instead of in every &lt;code&gt;Update&lt;/code&gt; call.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now our ActionableObject:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActionableObject&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IActionableObject&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"UI"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Tooltip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The text that will appear in the overlay before interacting with this object"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;interactionText&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"open"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Tooltip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The text that will appear in the overlay after interacting with this object"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;interactionTextReverse&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"close"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;m_interacted&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;m_interactive&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&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;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;InnerStart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InnerStart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GetInteractionText&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="n"&gt;m_interacted&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;interactionText&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;interactionTextReverse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Interact&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;InnerInteract&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;m_interacted&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;m_interacted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InnerInteract&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsInteracterActive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m_interactive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;SetIsInteractive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isInteractive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m_interactive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;isInteractive&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;This class must be abstract because we need to force a specific implementation for each type of actionable object.&lt;/p&gt;

&lt;p&gt;First, we define some serialized fields that we will need. The &lt;code&gt;interactionText&lt;/code&gt; is "open" by default (remember we are prepending it with the &lt;code&gt;m_initialText&lt;/code&gt; of the &lt;code&gt;InteractionText&lt;/code&gt;). The &lt;code&gt;interactionTextReverse&lt;/code&gt; is the text to show to "reverse" the action (if needed). For example open/close.&lt;/p&gt;

&lt;p&gt;The attributes &lt;code&gt;m_interacted&lt;/code&gt; and &lt;code&gt;m_interactive&lt;/code&gt; indicates whether the object is in the "interacted" state (interacted and not reverted) and if is interactive, respectively.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Start&lt;/code&gt; method does nothing else than calling an abstract &lt;code&gt;InnerStart&lt;/code&gt;. This is done in order to avoid a reimplementation of the generic &lt;code&gt;Start&lt;/code&gt; without calling the super. This is useful when we need to force some behaviour in the parent class that cannot be overriden (as in the &lt;code&gt;Interact&lt;/code&gt; function). Is some sort of &lt;a href="https://en.wikipedia.org/wiki/Template_method_pattern#:~:text=The%20template%20method%20is%20a,class%20as%20the%20template%20method." rel="noopener noreferrer"&gt;template method&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GetInteractionText&lt;/code&gt; just returns the interaction text or the reverse one depending on the &lt;code&gt;m_interacted&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Interact&lt;/code&gt; is similar to the &lt;code&gt;Start&lt;/code&gt; function. It's called when the object is interacted and just calls the &lt;code&gt;InnerInteract&lt;/code&gt; (which will hold the specific interaction code) and flips the &lt;code&gt;m_interacted&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IsInteracterActive&lt;/code&gt; and &lt;code&gt;SetIsInteractive&lt;/code&gt; are the getter and setter for the &lt;code&gt;m_interactive&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;And that's all for this step! We have just implemented our generic actionable objects! Let's move to the next step!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember, you have the code developed in this step &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors/tree/step-2" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3: Standard actionable objects
&lt;/h2&gt;

&lt;p&gt;Here we are going to implement the specific class for a standard actionable object. This means that it's not actionable by key, that triggers an animation and that is "reversible" (you can, for example, open and close a door). I consider this the standard since it was the first type of actionable object I implemented and will be the one which will be used more extensively in our game.&lt;/p&gt;

&lt;p&gt;You may remember that we used some hardcoded strings in the editor when setting up the animations (a parameter called "direction"). Instead of using literals we are going to extract that to constants, to avoid having hardcoded strings across all our codebase.&lt;/p&gt;

&lt;p&gt;Create a folder called "Constants" inside our "Scripts" folder and, inside it, create a file called "Animation":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;AnimateDoors.Animation&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnimationConstants&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ANIMATION_DIRECTION&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"direction"&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;We are isolating those constants in the &lt;code&gt;Animation&lt;/code&gt; namespace to avoid collisions with the script name and the Unity Animation component. We are defining a constant called &lt;code&gt;ANIMATION_DIRECTION&lt;/code&gt; with the direction parameter name.&lt;/p&gt;

&lt;p&gt;Now let's create our &lt;code&gt;StandardActionableObject&lt;/code&gt; class inside our &lt;code&gt;Scripts/ActionableObjects&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;RequireComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Animator&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StandardActionableObject&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ActionableObject&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Animation"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Tooltip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The animation state to play when interacting with this object"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SerializeField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;animationState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;Animator&lt;/span&gt; &lt;span class="n"&gt;m_animator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InnerStart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m_animator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GetComponent&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Animator&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;        
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InnerInteract&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;UpdateAnimation&lt;/span&gt;&lt;span class="p"&gt;();&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;void&lt;/span&gt; &lt;span class="nf"&gt;UpdateAnimation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m_animator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AnimationConstants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ANIMATION_DIRECTION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;m_interacted&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="m"&gt;1f&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;m_animator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;animationState&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;First we are going to require the Animator component to trigger the animation.&lt;/p&gt;

&lt;p&gt;Then, define an attribute to store the name of the state in the animator to play when the object is interacted.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;InnerStart&lt;/code&gt; will just store a reference to the &lt;code&gt;Animator&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;InnerInteract&lt;/code&gt; will call to &lt;code&gt;UpdateAnimation&lt;/code&gt; and, that one, will set the "direction" parameter to 1 or -1 depending on the &lt;code&gt;m_interacted&lt;/code&gt; flag. Remember that the &lt;code&gt;direction&lt;/code&gt; controls the speed of the animation. If the object has not been interacted we are going to set the speed value to 1 and the animation will be played forward. If it has been interacted, the direction will be -1, so it will be played backwards. Right after that, we will play the state stored in the &lt;code&gt;animationState&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;And that's all! Easy, right? That's why we invested some time in the parent class, so the children are easy to implement.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Access the code of this step &lt;a href="https://github.com/alesanmed-blog-posts/unity-animate-doors/tree/step-3" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let me stop here for now and finish the implementation in a following post. In the next one we will implement the specific classes for each type of actionable object and set everything up in the editor to use it.&lt;/p&gt;

&lt;p&gt;Please feel free to make any suggestions and propose improvements to the code in this post, as well as any doubt you might have! Stay tuned for the next post in which we will finish implementing our key objects! &lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Generating Microservices with NestJS and schematics</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Sat, 10 Oct 2020 10:40:34 +0000</pubDate>
      <link>https://dev.to/alesanchez/generating-microservices-with-nestjs-and-schematics-1091</link>
      <guid>https://dev.to/alesanchez/generating-microservices-with-nestjs-and-schematics-1091</guid>
      <description>&lt;p&gt;Welcome back to another super post about microservices and NestJS! We have been working on this project for a while and I decided to share with you how to use this and why we built a template project. So... let's begin!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rebember&lt;/strong&gt;: the template project generator package is publicly hosted in &lt;a href="https://github.com/rebellionpay/microservices-template" rel="noopener noreferrer"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What are schematics?
&lt;/h1&gt;

&lt;p&gt;If you don't know what schematics are, I'll do a quick overview about what are they. But I recommend you to take a look at the &lt;a href="https://angular.io/guide/schematics" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To sum it up, schematics are some sort of blueprints but for code. Yo define with a special templating language the files you want to generate and the run the schematics engine on it for generating the final files.&lt;/p&gt;

&lt;p&gt;And what does all of this to do with NestJS? The cool thing is that &lt;a href="https://docs.nestjs.com/cli/overview" rel="noopener noreferrer"&gt;Nest CLI&lt;/a&gt; uses angular schematics under the hood and, even better, they allow you to reference a custom collection with schematics!&lt;/p&gt;

&lt;p&gt;That means that you can create your custom schematics and still get all the features from the Nest CLI, cool right??&lt;/p&gt;

&lt;h1&gt;
  
  
  Why a project generator?
&lt;/h1&gt;

&lt;p&gt;We in Rebellion believe a lot in the concept that Netflix used in one of their tech talks, which is the knonw "Paved roads".&lt;/p&gt;

&lt;p&gt;Paved roads mean (from my point of view) develop and have the tools needed for speeding up repetitive tasks.&lt;/p&gt;

&lt;p&gt;For example, everytime we have to create a new project for a microservice we have to generate the default NestJS project, add the microservices package, add the NATS package, add persistence layer, create some global interceptors... These set of tasks are always the same and can be automated in an easy way. And that way is using a generator with schematics.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to use it?
&lt;/h1&gt;

&lt;p&gt;Using the project is simple, you just have to install it as a global NPM package and reference it in the Nest CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @rebellionpay/nest-ms-template

&lt;span class="c"&gt;# for generating an app&lt;/span&gt;
nest g &lt;span class="nt"&gt;-c&lt;/span&gt; @rebellionpay/nest-ms-template app

&lt;span class="c"&gt;# for generating a controller&lt;/span&gt;
nest g &lt;span class="nt"&gt;-c&lt;/span&gt; @rebellionpay/nest-ms-template ctrl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you just have to answer the questions and the files are going to be generated.&lt;/p&gt;

&lt;h1&gt;
  
  
  What includes this template?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;THIS IS REALLY IMPORTANT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This project is, as said, a paved road &lt;strong&gt;for rebellion pay&lt;/strong&gt;. This means that the functionalities included are the ones that fit the needs of our company and our team.&lt;/p&gt;

&lt;p&gt;Being that said, let me guide you through the generated files of a project.&lt;/p&gt;

&lt;p&gt;Let me put the answers given to the questions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? What name would you like to use for the new project? sample-project
? Who is the author of the project? Rebellion Pay &amp;lt;backend@rebellionpay.com&amp;gt;
? Which is the description of the project? This is a sample project
? Which is the project license? MIT
? In which port will it run? 3000
? Which transport layer would you like to use? NATS
? Are you building a pure app? No
? Are you going to use persistence in a DB? Yes
? Which database would you like to use? mongodb
? Are you going to make the CD with spinnaker? Yes
? What is the spinnaker API url? https://testing.spinnaker.com
? In which kubernetes namespace will this app going to be deployed? default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For that set of answers, the following files are generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── .vscode
│   └── launch.json
├── kubernetes
│   └── manifest.yml
├── src
│   ├── config
│   │   ├── MongoConfigService.ts
│   │   └── NATSConfigService.ts
│   ├── factory
│   │   └── winstonConfig.ts
│   ├── filters
│   │   └── ExceptionsFilter.ts
│   ├── interceptors
│   │   ├── InjectMetadataInterceptor.ts
│   │   ├── MetricsInterceptor.ts
│   │   └── TimeoutInterceptor.ts
│   ├── interface
│   │   └── MicroserviceMessage.ts
│   ├── message
│   │   ├── message.module.ts
│   │   ├── message.service.spec.ts
│   │   └── message.service.ts
│   ├── metrics
│   │   ├── metrics.module.ts
│   │   └── metrics.service.ts
│   ├── app.controller.spec.ts
│   ├── app.controller.ts
│   ├── app.module.ts
│   ├── app.service.ts
│   └── main.ts
├── test
│   ├── app.e2e-spec.ts
│   └── jest-e2e.json
├── .env.example
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .gitlab-ci.yml
├── .prettierrc
├── README.md
├── nest-cli.json
├── package.json
├── tsconfig.build.json
└── tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the root folder we have a standard README file, the Typescript config files, a package.json and a nest-cli.json, which is used for monorepo projects. We have also a sample .env file and the ESLint/prettier config files. And, lastly, a gitignore and a gitlab CI file.&lt;/p&gt;

&lt;p&gt;There are also a &lt;code&gt;.vscode&lt;/code&gt; and a &lt;code&gt;kubernetes&lt;/code&gt; folder. The .vscode folder has a &lt;code&gt;launch.json&lt;/code&gt; with a standard config for nestjs projects. The kubernetes folder contains a manifest file with a service and a deployment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We are going to use block quotes to explain the differences in the code if you choose other alternatives to the questions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  main.ts
&lt;/h2&gt;

&lt;p&gt;In the src folder we have the &lt;code&gt;main.ts&lt;/code&gt; file. There is the function that bootstraps the nest app. In the case of our answers the &lt;code&gt;main.ts&lt;/code&gt; bootstraps an &lt;a href="https://docs.nestjs.com/faq/hybrid-application" rel="noopener noreferrer"&gt;hybrid app&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&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="nf"&gt;initializeAPMAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ELASTIC_APM_SERVER_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ELASTIC_APM_SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;secretToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ELASTIC_APM_SECRET_TOKEN&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bootstrap&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;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoggerConfig&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;LoggerConfig&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;winstonLogger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;WinstonModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;console&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;cors&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="na"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WinstonLogger&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;natsConfigService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NATSConfigService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&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;NATSConfigService&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;configService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ConfigService&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;ConfigService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;helmet&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useGlobalFilters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AllExceptionsFilter&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;


  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connectMicroservice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;natsConfigService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getNATSConfig&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;globalInterceptors&lt;/span&gt; &lt;span class="o"&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&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="nx"&gt;globalInterceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;app&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;ApmHttpUserContextInterceptor&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;app&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;ApmErrorInterceptor&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;apmMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;app&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;APM_MIDDLEWARE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apmMiddleware&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;globalInterceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TimeoutInterceptor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useGlobalInterceptors&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt; &lt;span class="nx"&gt;globalInterceptors&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="nx"&gt;configService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;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;PORT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startAllMicroservicesAsync&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;app&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;winstonLogger&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;`Hybrid sample-project test running on port &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="p"&gt;));&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we start configuring the APM agent for sending data to APM. This is one of the tools we use for gathering metrics of our services.&lt;/p&gt;

&lt;p&gt;We also use Winston for logging. That's why we instantiate the logger in the first place and pass it to the nest factory.&lt;/p&gt;

&lt;p&gt;Then we add a global interceptor and a global filter. If we are in production, we finish setting up APM and pusing the interceptors.&lt;/p&gt;

&lt;p&gt;The filter we are using is for catching all exceptions that occurs in the app.&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Catch&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;AllExceptionsFilter&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ExceptionFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ArgumentsHost&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switchToHttp&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;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRequest&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getResponse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&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="nx"&gt;exception&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;HttpException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&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="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;You can see that the filter just catches the exceptions and returns a standard response.&lt;/p&gt;

&lt;p&gt;On the other hand, the timeout interceptor just acts on every message sent and if it takes more than 5 seconds to resolve, it throws an exception.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you choose a pure app, the code is almost the same. But we don't have to define any port and the metadata interceptor can be used also as a global one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  app.*.ts
&lt;/h2&gt;

&lt;p&gt;The app.*.ts files contains the main module code.&lt;/p&gt;

&lt;h3&gt;
  
  
  app.module.ts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&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;AppModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;DynamicModule&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;imports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;MongooseModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRootAsync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;useClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MongoConfigService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="nx"&gt;WinstonModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;console&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
      &lt;span class="nx"&gt;ConfigModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;isGlobal&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="na"&gt;validationSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiObject&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&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;production&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;test&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;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiNumber&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;port&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3030&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;ELASTIC_APM_SERVER_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;ELASTIC_APM_SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;ELASTIC_APM_SECRET_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;NATS_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nats://localhost:4222&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;NATS_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;NATS_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;MONGODB_URI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;INFLUX_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;JoiString&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;uri&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="nx"&gt;MetricsModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;MessageModule&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&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="nx"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ApmModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRootAsync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;useFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;httpUserMapFunction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&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="p"&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;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controllers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AppController&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;providers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NATSConfigService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AppService&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="na"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;providers&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we are using a dynamic module. We need to use that because we can register the APM module only in production.&lt;/p&gt;

&lt;p&gt;We use joi for validating the config that has to be present in the .env file.&lt;/p&gt;

&lt;p&gt;In this case we are using mongoose for persistence but there is an option for choosing also MySQL and PostgreSQL.&lt;/p&gt;

&lt;p&gt;We also import two modules, the metrics and message modules.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you choose a pure app the metrics interceptor is going to be used also as a provider.&lt;/p&gt;

&lt;p&gt;If you use a different persistence layer you will see there another different config service injected there. If no persistence chosen, no config service injected.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  metrics|message.module.ts
&lt;/h3&gt;

&lt;p&gt;The metrics module is simple and is used with the metrics interceptor. The interceptor is just placed in the middle of every request (http or rpc) and calls the metrics service to send a few data to our metrics infrastructure, influxdb.&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;MetricsService&lt;/span&gt; &lt;span class="p"&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="nx"&gt;configService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigService&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="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;influx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Influx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;InfluxDB&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;configService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&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="o"&gt;&amp;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;INFLUX_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:8086/telegraf&lt;/span&gt;&lt;span class="dl"&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;measurement&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="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&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="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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="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;influx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writePoints&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;
      &lt;span class="nx"&gt;measurement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;fields&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;It is what it is, a service for sending metrics to influxdb.&lt;/p&gt;

&lt;p&gt;Then we have the message module. That module just imports the message service which implements the same functions the NestJS &lt;code&gt;ClientProxy&lt;/code&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;MessageService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MESSAGE_CLIENT&lt;/span&gt;&lt;span class="dl"&gt;'&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;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClientProxy&lt;/span&gt;&lt;span class="p"&gt;){};&lt;/span&gt;

  &lt;span class="nx"&gt;sendMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Toutput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Tinput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&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;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&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="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&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;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tinput&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;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Toutput&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;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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Toutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tinput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;emitMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Toutput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Tinput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&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;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&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="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&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;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tinput&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;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Toutput&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;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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Toutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceMessage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tinput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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;We use our wrapping functions because we want to centralize the sending of the messages in the same place and if, at some point, we need to implement more metrics, controls or whatever in the sending of messages, we just have to put it in one place.&lt;/p&gt;

&lt;p&gt;We also define our own MicroserviceMessage interface which includes, besides the pattern and payload, some metadata we use for logging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interceptors
&lt;/h3&gt;

&lt;p&gt;In the project we have 3 interceptors. One for the metrics, one for the metadata and a timeout interceptor. The timeout has already been explained above.&lt;/p&gt;

&lt;p&gt;The metadata interceptor is another simple interceptor. It just takes every RPC message, gets the pattern of the message (as we use NATS) and injects it into the message payload. We use this so that, for each request, we can print the metadata of the message with the message pattern that triggered that log line. This allow us to trace (for a specific request ID) every message pattern sent in a user flow.&lt;/p&gt;

&lt;p&gt;And the metrics interceptor is just an interceptor to send metrics using the previously seen metric service. It just acts on each request and depending on the request type (HTTP or RPC) gathers different metrics. At the end, it send those metrics to influx using the metrics service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example service and controller
&lt;/h3&gt;

&lt;p&gt;We also generate an &lt;code&gt;app.service.ts&lt;/code&gt; and an &lt;code&gt;app.controller.ts&lt;/code&gt; to illustrate the required configuration for each of them.&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;UseInterceptors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MetricsInterceptor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;InjectMetadataInterceptor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&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;AppController&lt;/span&gt; &lt;span class="p"&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;appService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AppService&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;messageService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MessageService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;WINSTON_MODULE_PROVIDER&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;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;MessagePattern&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_CMD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nf"&gt;yourMessageHandler&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceMessage&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Record&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;unknown&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&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="nd"&gt;Post&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;yourPostHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&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="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-request-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;reqId&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;unknown&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;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reqId&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;response&lt;/span&gt; &lt;span class="o"&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;messageService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_CMD&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reqId&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;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPromise&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;data&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="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nf"&gt;getHello&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="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;appService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHello&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="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;getStatus&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="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[OK]&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;p&gt;The main things here are the interceptors used. The metrics and metadata interceptors has to be injected here because in an hybrid app, if you use them globally they are going to be triggered only for HTTP requests.&lt;/p&gt;

&lt;p&gt;Every other functions are standard controller functions with an example message pattern.&lt;/p&gt;

&lt;p&gt;We use the annotation &lt;code&gt;@Headers('x-request-id') reqId: string&lt;/code&gt; because we use Kong as gateway and have a plugin set up to assign a unique ID to each request.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you use a pure app the interceptors are not going to be put there because the can be used globally. Also you will not have the HTTP endpoints.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  BONUS TRACK: Generating controllers
&lt;/h2&gt;

&lt;p&gt;As I said, the controllers are different if you are using a pure app or an hybrid one. That's why the template project also supports generating a controller. The questions are really simple and the only difference between a pure app controller or an hybrid app one are the interceptors.&lt;/p&gt;

&lt;p&gt;If you use a pure app they won't be injected and if you don't, they will.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;As said in the beginning of the post, this is a pave road for our company. I think this is a cool project and can either act as a starting point for someone else's project or be useful for anyone to bootstrap own microservices projects.&lt;/p&gt;

&lt;p&gt;Please, feel free to comment if you want me to write another post talking about the technical part of the schematics and how I built this template project.&lt;/p&gt;

&lt;p&gt;Also feel free to fill an issue in the &lt;a href="https://github.com/rebellionpay/microservices-template" rel="noopener noreferrer"&gt;project repo&lt;/a&gt; if you miss something or even open a pull request.&lt;/p&gt;

&lt;p&gt;See you in the next post!! &lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>schematics</category>
      <category>microservices</category>
      <category>templating</category>
    </item>
    <item>
      <title>Building authentication for microservices using NestJS</title>
      <dc:creator>Ale Sánchez</dc:creator>
      <pubDate>Sat, 11 Apr 2020 12:55:51 +0000</pubDate>
      <link>https://dev.to/alesanchez/building-authentication-for-microservices-using-nestjs-1fne</link>
      <guid>https://dev.to/alesanchez/building-authentication-for-microservices-using-nestjs-1fne</guid>
      <description>&lt;p&gt;Before all, the code used in this post can be found at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/alesanmed-blog-posts/nestjs-microservices-auth-auth" rel="noopener noreferrer"&gt;Authentication microservice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/alesanmed-blog-posts/nestjs-microservices-auth-user" rel="noopener noreferrer"&gt;Users microservice&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is NestJS? If you already know it you can skip this part. NestJS is a framework for building Node.JS applications. It gives you lots of advantages and tools for making them scalable and performant. One of the best parts is that NestJS has the tools needed for building microservices. You can achieve full transport independence, define messaging patterns as well as other things to make our life easier when developing microservices. &lt;/p&gt;

&lt;p&gt;If you're completely new to NestJS I recommend you to read &lt;a href="https://docs.nestjs.com/first-steps" rel="noopener noreferrer"&gt;the overview&lt;/a&gt; and the &lt;a href="https://docs.nestjs.com/techniques/authentication" rel="noopener noreferrer"&gt;authentication technique&lt;/a&gt;. And, since we are going to develop a couple of microservices, it's a good idea to read also the &lt;a href="https://docs.nestjs.com/microservices/basics" rel="noopener noreferrer"&gt;microservices part&lt;/a&gt;. I know that the read could take you some minutes, but it's worth it. I'll wait here!&lt;/p&gt;

&lt;p&gt;I'm going to assume in this post that you already read that, so I can skip some configuration and code that is already present there (and probably better explained 😝).&lt;/p&gt;

&lt;p&gt;In this post I'm going to use TypeScript and NPM. But just for the records, NestJS allows any combination of typescript or javascript with npm or yarn.&lt;/p&gt;

&lt;p&gt;The NestJS documentation shows how to build an application with the authentication and user management in the same place. What I want to show you is how to build that same thing, but for microservices.&lt;/p&gt;

&lt;p&gt;That will involve splitting the auth part from the user management part. And also you should be able to request the auth microservice authentication or authorization for a specific user and from any microservice in your network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flqhgf622rn73dtogtgmk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flqhgf622rn73dtogtgmk.png" alt="Microservices architecture with auth and users microservice"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image shows a simplified architecture without gateways or other things. As you can see, other microservices could be connected to the auth one the same way the user does.&lt;/p&gt;

&lt;p&gt;Let's start building our architecture...&lt;/p&gt;

&lt;h1&gt;
  
  
  Messaging between microservices
&lt;/h1&gt;

&lt;p&gt;NestJS provides us the tools needed to communicate between the microservices using message patterns. Why are message patterns so useful?&lt;/p&gt;

&lt;p&gt;Imagine we define a message like &lt;code&gt;{ role: 'user', cmd: 'check' }&lt;/code&gt; to be handled by a specific function. And now, imagine that in the future we want to upgrade or extend the functionality of that feature. We can add a new &lt;code&gt;{ role: 'user', cmd: 'check', type: 'newfeature' }&lt;/code&gt; message and the network will automatically redirect the new message to a new function which, inside, can end by sending a &lt;code&gt;{ role: 'user', cmd: 'check' }&lt;/code&gt; message. &lt;/p&gt;

&lt;p&gt;With that approach we can extend our architecture with new features without modifying, stopping or deleting old microservices, just adding new ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining our messages
&lt;/h2&gt;

&lt;p&gt;So let's elaborate the list of messages and request we are going to use in our architecture. First, what do we want to achieve?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticate a user in the auth service&lt;/li&gt;
&lt;li&gt;Retrieve a user by user id from the user service&lt;/li&gt;
&lt;li&gt;Authorize logged in users (and check if their login is valid) &lt;/li&gt;
&lt;li&gt;Protect a route and make it only available to authorized users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first requirement we don't really need a message, because that's going to be done with a &lt;code&gt;POST&lt;/code&gt; request. And the request will be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

POST /auth   Body: { username: string, password: string }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For the second requirement we need a message. For retrieving a user we are going to use:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Pattern:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Payload:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&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;And, for checking if a user is authenticated or not:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Pattern:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;check&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Payload:&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&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;For the last requirement, we are going to define the following route:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

GET /greet


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That will only be accessible by authenticated users.&lt;/p&gt;

&lt;p&gt;Those messages give us a natural split in two different microservices, the auth and the users one. So let's build them!&lt;/p&gt;

&lt;h1&gt;
  
  
  Auth microservice
&lt;/h1&gt;

&lt;p&gt;First of all we are going to generate our authentication microservice using nest-cli. If you don't have nest-cli installed, install it with:&lt;/p&gt;

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

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @nestjs/cli


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the cli is installed, we can generate our microservice with the command:&lt;/p&gt;

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

nest new auth


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That command will generate a new empty NestJS project. Now let's install our dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Auth service dependencies
&lt;/h2&gt;

&lt;p&gt;For this post, we are going to use TCP as transporter and, as shown in the authentication guide, passport. Also we have to install the nest/microservices package. So let's do that them:&lt;/p&gt;

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

&lt;span class="nb"&gt;cd &lt;/span&gt;auth
npm i &lt;span class="nt"&gt;-S&lt;/span&gt; @nestjs/microservices @nestjs/passport @nestjs/jwt passport passport-local passport-jwt bcrypt
npm i &lt;span class="nt"&gt;--D&lt;/span&gt; @types/passport-local @types/passport-jwt @types/bcrypt


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Auth service development
&lt;/h2&gt;

&lt;p&gt;With everything installed we can start developing the microservice. The first thing is, as you know, change the &lt;code&gt;main.ts&lt;/code&gt; file to make it a &lt;a href="https://docs.nestjs.com/faq/hybrid-application#hybrid-application" rel="noopener noreferrer"&gt;hybrid application&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;main.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bootstrap&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connectMicroservice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4000&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startAllMicroservicesAsync&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;app&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="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;Logger&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Auth microservice running&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="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is a standard bootstrap function. We are using TCP transport for simplicity, but if we want to avoid the need of a service discovery or the anti-pattern of hard-coding other microservices locations (as we are going to do in this post), we should use a message queue (like NATS, Kafka, RabbitMQ...).&lt;/p&gt;

&lt;p&gt;Now that we have the main file ready, let's take a look at the &lt;code&gt;AppModule&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;app.module.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;providers&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see, we have removed every providers and controllers, because they are going to be inside the &lt;code&gt;AuthModule&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now we have to define our &lt;code&gt;AuthModule&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;auth/auth.module.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;]&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;AuthModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For now we are going to put only our &lt;code&gt;AuthService&lt;/code&gt; as a provider, since we haven't implemented anything else yet. As you may know, we have to implement the user validation function. We are going to do that in our &lt;code&gt;AuthService&lt;/code&gt;. This is the first point in which we are going to take advantage of the microservices architeture.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;auth/auth.service.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;AuthService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USER_CLIENT&lt;/span&gt;&lt;span class="dl"&gt;'&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;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClientProxy&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;jwtService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JwtService&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;validateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&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="nx"&gt;password&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="kr"&gt;any&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;try&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;user&lt;/span&gt; &lt;span class="o"&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;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&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="nx"&gt;username&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
        &lt;span class="nf"&gt;catchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;TimeoutError&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="nf"&gt;throwError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RequestTimeoutException&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="nf"&gt;throwError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="nf"&gt;toPromise&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="nf"&gt;compareSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&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;password&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="nx"&gt;user&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Logger&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;e&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="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;login&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&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="na"&gt;sub&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;id&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="na"&gt;userId&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accessToken&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;jwtService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&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="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see here, we are introducing new concepts. The &lt;code&gt;login&lt;/code&gt; function is the same as in the docs, so no need to explain much, just takes the payload and issues a JWT. We also injected the JwtService the same way the doc does, so let's review &lt;code&gt;validateUser&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;First of all we are sending a message to another microservice. For that we are using the NestJS &lt;code&gt;ClientProxy&lt;/code&gt; injectable. That client proxy has to be configured elsewhere (we'll se later), and gives us helper functions to send messages or emit events to other microservices.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;send&lt;/code&gt; function is returning an &lt;code&gt;Observable&lt;/code&gt;, so we are taking advantage of that and piping it. If the response takes (for whatever reason) more than 5 seconds, we are forcing a timeout error.&lt;/p&gt;

&lt;p&gt;If the message is answered correctly, we are going to compare the received user password with the password received in the API request. We use a &lt;a href="https://blog.ircmaxell.com/2014/11/its-all-about-time.html" rel="noopener noreferrer"&gt;timing-safe&lt;/a&gt; function for comparing the passwords. If it's correct we return the user (successful authentication), otherwise we return null (failed authentication).&lt;/p&gt;

&lt;p&gt;But how can we inject and where should we configure the &lt;code&gt;ClientProxy&lt;/code&gt;? Of course, in our &lt;code&gt;AuthModule&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;auth/auth.module.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ClientsModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&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;USER_CLIENT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4010&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="nx"&gt;JwtModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yoursecret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;signOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;60s&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;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;]&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;AuthModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We imported the &lt;code&gt;ClientsModule&lt;/code&gt; configured with the same transport as our microservice &lt;em&gt;but&lt;/em&gt; pointing the microservice we want to send messages to (maybe yo want to use the &lt;code&gt;ConfigModule&lt;/code&gt; for not having to repeat the configurations).&lt;/p&gt;

&lt;p&gt;Please take into account that the &lt;code&gt;name&lt;/code&gt; we put in the &lt;code&gt;ClientsModule&lt;/code&gt; has to be the same we put in the &lt;code&gt;@Inject&lt;/code&gt; decorator. We also added the JwtModule as in the documentation.&lt;/p&gt;

&lt;p&gt;The next step is to implement our local and jwt strategies. Since this part is exactly the same as the one in the documentation I'm just going to put the code here but I'm not going to go through it.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;auth/local.strategy.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;LocalStrategy&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PassportStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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;authService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&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="nx"&gt;password&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="kr"&gt;any&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;user&lt;/span&gt; &lt;span class="o"&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;authService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&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="nx"&gt;user&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;UnauthorizedException&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="nx"&gt;user&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;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;auth/jwt.strategy.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JwtStrategy&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PassportStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;jwtFromRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExtractJwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromAuthHeaderAsBearerToken&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;ignoreExpiration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;secretOrKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yoursecret&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;async&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&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="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 we have to add the strategy as a provider in our module:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;auth/auth.module.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ClientsModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&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;USER_CLIENT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4010&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="nx"&gt;JwtModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yoursecret&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;signOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;60s&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;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LocalStrategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JwtStrategy&lt;/span&gt;&lt;span class="p"&gt;]&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;AuthModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now the last part is, as in the docs, create our &lt;code&gt;AuthGuard&lt;/code&gt; with the local strategy. No explanation needed here:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;&lt;code&gt;auth/local-auth.guard.ts&lt;/code&gt;&lt;/em&gt;
&lt;/h4&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;LocalAuthGuard&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AuthGuard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;local&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="s2"&gt;```

We are not creating the jwt auth guard, because we are going to implement the authorization in a different way.

The last part is to create our `&lt;/span&gt;&lt;span class="nx"&gt;AuthController&lt;/span&gt;&lt;span class="s2"&gt;`:

#### *`&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&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;AuthController&lt;/span&gt; &lt;span class="p"&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;authService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&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="nd"&gt;UseGuards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LocalAuthGuard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&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;login&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Request&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="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;authService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&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;user&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="s2"&gt;```

This part is the same as the one in the documentation. With this controller, our module will look like this:

#### *`&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ClientsModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&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;USER_CLIENT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4010&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="nx"&gt;JwtModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwtSecret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;signOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;60s&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;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LocalStrategy&lt;/span&gt;&lt;span class="p"&gt;]&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;AuthModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="s2"&gt;```

Let's review what we have until this moment. We have our auth microservice set up accepting a `&lt;/span&gt;&lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="s2"&gt;` request to `&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="s2"&gt;` for authenticating a user. That endpoint receives a username and a password and gets the user entity from another microservice not built yet. Based on that response is going to compare the passwords and authenticate or not the user. If you run the microservice with `&lt;/span&gt;&lt;span class="nx"&gt;nest&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="s2"&gt;` it should start up, but if you try to make a `&lt;/span&gt;&lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="s2"&gt;` request to that service you are going to get a `&lt;/span&gt;&lt;span class="nx"&gt;TimeoutError&lt;/span&gt;&lt;span class="s2"&gt;`. So...

Let's go into our second microservice!

# User microservice

As well as we did with the auth microservice, let's generate the application.

```&lt;/span&gt;&lt;span class="nx"&gt;bash&lt;/span&gt;
&lt;span class="nx"&gt;nest&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;
&lt;span class="s2"&gt;```

## User service dependencies

Let's now install the dependencies. Here we don't need passport or strategies, but we do need some data persistence. We are going to use PostgreSQL as persistence layer and [TypeORM](https://docs.nestjs.com/techniques/database) as orm.

```&lt;/span&gt;&lt;span class="nx"&gt;bash&lt;/span&gt;
&lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;
&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;S&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nestjs&lt;/span&gt;&lt;span class="sr"&gt;/microservices @nestjs/&lt;/span&gt;&lt;span class="nx"&gt;typeorm&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="nx"&gt;pg&lt;/span&gt; &lt;span class="nx"&gt;typeorm&lt;/span&gt;
&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;types&lt;/span&gt;&lt;span class="sr"&gt;/bcryp&lt;/span&gt;&lt;span class="err"&gt;t
&lt;/span&gt;&lt;span class="s2"&gt;```

## User service development

The first step is, again, adapt our `&lt;/span&gt;&lt;span class="nx"&gt;bootstrap&lt;/span&gt;&lt;span class="s2"&gt;` function to the microservices pattern:

### *`&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bootstrap&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connectMicroservice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4010&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startAllMicroservicesAsync&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;app&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="mi"&gt;3010&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="s2"&gt;```

Same thing as with the auth service, but with different ports. I like to increase port numbers 10 by 10, but it's just a personal way of doing it.

Now that our service is ready to run as an hybrid application, let's create our `&lt;/span&gt;&lt;span class="nx"&gt;UserEntity&lt;/span&gt;&lt;span class="s2"&gt;`. That will be the object that is going to represent (thanks to `&lt;/span&gt;&lt;span class="nx"&gt;TypeORM&lt;/span&gt;&lt;span class="s2"&gt;`) the users in our database:

### *`&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&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;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Unique&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&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="nd"&gt;Unique&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&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;User&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;UserInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;PrimaryGeneratedColumn&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;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;username&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="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;password&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="nd"&gt;Column&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;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;IsEmail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;email&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="nd"&gt;CreateDateColumn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;BeforeInsert&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;hashPassword&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;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;hash&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;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&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="s2"&gt;```

This is a standard entity representing a standard user with username, password, email and name. We added an autogenerated `&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="s2"&gt;` field and a function that is going to be run before every insertion to hash the password.

&amp;gt; You can import the `&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="s2"&gt;` function from the `&lt;/span&gt;&lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="s2"&gt;` package.

And the `&lt;/span&gt;&lt;span class="nx"&gt;UserInterface&lt;/span&gt;&lt;span class="s2"&gt;` is just:

### *`&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&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;UserInterface&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;number&lt;/span&gt;
  &lt;span class="nx"&gt;username&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;password&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;name&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;email&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="s2"&gt;```

Now we have to build our `&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="s2"&gt;` to set up the `&lt;/span&gt;&lt;span class="nx"&gt;TypeORM&lt;/span&gt;&lt;span class="s2"&gt;` module:

### *`&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TypeOrmModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ms-user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ms-user-pass&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ms-user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;synchronize&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="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;})],&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;AppModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="s2"&gt;```

The `&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="s2"&gt;` array contains just one, our `&lt;/span&gt;&lt;span class="nx"&gt;UserEntity&lt;/span&gt;&lt;span class="s2"&gt;` previously defined.

&amp;gt; Tip: For running a PostgreSQL server locally I highly recommend you use their official (docker image)[https://hub.docker.com/_/postgres]

With that in place, let's look at our `&lt;/span&gt;&lt;span class="nx"&gt;UsersService&lt;/span&gt;&lt;span class="s2"&gt;`. The one responsible of working with the database and user entities:

### *`&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&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;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectRepository&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;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;findOne&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="nx"&gt;FindConditions&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;User&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;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;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&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="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createUser&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="kr"&gt;any&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;InsertResult&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/**
       * Perform all needed checks
       */&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userEntity&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;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&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;userRepository&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;userEntity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;Logger&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createUser - Created user&lt;/span&gt;&lt;span class="dl"&gt;'&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;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Logger&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;e&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="p"&gt;}&lt;/span&gt;
&lt;span class="s2"&gt;```

Nothing special there, just functions for inserting and retrieving users. But let's look at the fun part... The `&lt;/span&gt;&lt;span class="nx"&gt;UserController&lt;/span&gt;&lt;span class="s2"&gt;`.

### *`&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&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;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&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;UserController&lt;/span&gt; &lt;span class="p"&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;userService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserService&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;MessagePattern&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;'&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;User&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;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;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&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="s2"&gt;```

That starts to look familiar. We just implemented our message pattern for the user microservice. This function must not be protected because our auth microservice needs to ask it for the user trying to authenticate. That function will only check in the database if the user exists and, if exists, will send back to the auth microservice.

So our `&lt;/span&gt;&lt;span class="nx"&gt;UserModule&lt;/span&gt;&lt;span class="s2"&gt;` will look like this:

### *`&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;TypeOrmModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forFeature&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="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;],&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;UserModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="s2"&gt;```

We have to register again the `&lt;/span&gt;&lt;span class="nx"&gt;TypeOrm&lt;/span&gt;&lt;span class="s2"&gt;` module for the `&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="s2"&gt;` feature and, of course, we have to import this module into our root `&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="s2"&gt;`:

### *`&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TypeOrmModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pass&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user-microservice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;synchronize&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="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&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="p"&gt;})],&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;AppModule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="s2"&gt;```

Let's summarize again what we have until now!

We built an authentication microservice which accepts a `&lt;/span&gt;&lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="s2"&gt;` request with user and password. That microservice asks via message to our user microservice for the details of that user. Compares the user's password and the received password. If they are different, returns an Unauthorized error. If they are the same, it issues a JWT and returns it to the client. Cool, right??

For testing full flow you first have to insert some users to your Postgres database, for example `&lt;/span&gt;&lt;span class="nx"&gt;user1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="s2"&gt;`. Now run your microservices:

```&lt;/span&gt;&lt;span class="nx"&gt;bash&lt;/span&gt;
&lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;
&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;
&lt;span class="s2"&gt;```

And

```&lt;/span&gt;&lt;span class="nx"&gt;bash&lt;/span&gt;
&lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;
&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;
&lt;span class="s2"&gt;```

Now our `&lt;/span&gt;&lt;span class="nx"&gt;POST&lt;/span&gt;&lt;span class="s2"&gt;` request should look like:

```&lt;/span&gt;&lt;span class="nx"&gt;bash&lt;/span&gt;
&lt;span class="nx"&gt;curl&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;POST&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type: application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{
    "username": "user1",
    "password": "password"
}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="s2"&gt;```

That request should return you:

```&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accessToken&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="s2"&gt;ey...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="s2"&gt;```

But if you send an incorrect username or password, you should get an Unauthorized error.

# User and auth service together

Ok, you made progress so far, but it seems that there is one more thing missing...

We can now authenticate users, but we also need to authorize them! How can we protect routes in any microservice by using our strategies defined in the auth microservice?

First of all, we need our auth microservice to understand that it needs to handle another type of request, our `&lt;/span&gt;&lt;span class="nx"&gt;check&lt;/span&gt;&lt;span class="s2"&gt;` message pattern. We are going to implement it in our `&lt;/span&gt;&lt;span class="nx"&gt;AuthController&lt;/span&gt;&lt;span class="s2"&gt;`:

#### *`&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&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;AuthController&lt;/span&gt; &lt;span class="p"&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;authService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&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="nd"&gt;UseGuards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LocalAuthGuard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&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;login&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Request&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="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;authService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&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;user&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="nd"&gt;MessagePattern&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;check&lt;/span&gt;&lt;span class="dl"&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;loggedIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&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;res&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;authService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validateToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwt&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;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Logger&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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="p"&gt;}&lt;/span&gt;
&lt;span class="s2"&gt;```

We added the `&lt;/span&gt;&lt;span class="nx"&gt;loggedIn&lt;/span&gt;&lt;span class="s2"&gt;` function that is going to handle the `&lt;/span&gt;&lt;span class="nx"&gt;check&lt;/span&gt;&lt;span class="s2"&gt;` message. This function just has to call the one in charge of validating the token. Let's see our `&lt;/span&gt;&lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="s2"&gt;` with that function implemented.

#### *`&lt;/span&gt;&lt;span class="nx"&gt;AUTH&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;AuthService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USER_CLIENT&lt;/span&gt;&lt;span class="dl"&gt;'&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;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClientProxy&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;jwtService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JwtService&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;validateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&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="nx"&gt;password&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="kr"&gt;any&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;try&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;user&lt;/span&gt; &lt;span class="o"&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;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&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="nx"&gt;username&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
        &lt;span class="nf"&gt;catchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;TimeoutError&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="nf"&gt;throwError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RequestTimeoutException&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="nf"&gt;throwError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="nf"&gt;toPromise&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="nf"&gt;compareSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&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;password&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="nx"&gt;user&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Logger&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;e&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="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;login&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&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="na"&gt;sub&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;id&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="na"&gt;userId&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accessToken&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;jwtService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&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="nf"&gt;validateToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jwt&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;jwtService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jwt&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="s2"&gt;```

The new function just has to take the JWT received and call the `&lt;/span&gt;&lt;span class="nx"&gt;JwtService&lt;/span&gt;&lt;span class="s2"&gt;` to check whether the token received is valid or not. Simple.

Let's move back again to the user microservice and see how to use that new message pattern to protect routes.

First things firts, let's create a guard for protecting routes. As any guard, it has to have a `&lt;/span&gt;&lt;span class="nx"&gt;canActivate&lt;/span&gt;&lt;span class="s2"&gt;` function. That is the one in charge of asking to the auth service if the JWT is valid:

#### *`&lt;/span&gt;&lt;span class="nx"&gt;USER&lt;/span&gt; &lt;span class="nx"&gt;guards&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&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;AuthGuard&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanActivate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AUTH_CLIENT&lt;/span&gt;&lt;span class="dl"&gt;'&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;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ClientProxy&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;canActivate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExecutionContext&lt;/span&gt;&lt;span class="p"&gt;,&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;boolean&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;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switchToHttp&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;try&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;res&lt;/span&gt; &lt;span class="o"&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;check&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;jwt&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;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toPromise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&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;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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="p"&gt;}&lt;/span&gt;
&lt;span class="s2"&gt;```

We are injecting a `&lt;/span&gt;&lt;span class="nx"&gt;ClientProxy&lt;/span&gt;&lt;span class="s2"&gt;` to be able to send a message to our auth microservice. That client has to be configured (because we are using TCP) to reach the auth microservice. We'll do that in our `&lt;/span&gt;&lt;span class="nx"&gt;UserModule&lt;/span&gt;&lt;span class="s2"&gt;`.

In the guard we are just getting the request received, extracting the JWT (if present) and sending it to the auth microservice. If we get no response after 5 seconds, we just raise a timeout error. If we do get response, we let the request be processed or not based on that response. Easy!!

Now we just have to create a route and protect it using the `&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;UseGuard&lt;/span&gt;&lt;span class="s2"&gt;` decorator, and also register the `&lt;/span&gt;&lt;span class="nx"&gt;ClientsModule&lt;/span&gt;&lt;span class="s2"&gt;` for making the `&lt;/span&gt;&lt;span class="nx"&gt;ClientProxy&lt;/span&gt;&lt;span class="s2"&gt;` available in the guard. Let's create, for example, a `&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="s2"&gt;` route:

#### *`&lt;/span&gt;&lt;span class="nx"&gt;USER&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&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;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&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;UserController&lt;/span&gt; &lt;span class="p"&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;userService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserService&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;MessagePattern&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get&lt;/span&gt;&lt;span class="dl"&gt;'&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;User&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;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;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&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="nd"&gt;UseGuards&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AuthGuard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;greet&lt;/span&gt;&lt;span class="dl"&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;greet&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="kr"&gt;string&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;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Greetings authenticated user&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;span class="s2"&gt;```

The route is going to return a fixed text, but only if you provide a valid JWT.

And, finally, our `&lt;/span&gt;&lt;span class="nx"&gt;UserModule&lt;/span&gt;&lt;span class="s2"&gt;` has to look like this:

### *`&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="s2"&gt;`*
```&lt;/span&gt;&lt;span class="nx"&gt;typescript&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;TypeOrmModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forFeature&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;ClientsModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&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;AUTH_CLIENT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TCP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4000&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;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;],&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;UserModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="s2"&gt;```

Now we can all our login endpoint with valid credentials:

```&lt;/span&gt;&lt;span class="nx"&gt;bash&lt;/span&gt;
&lt;span class="nx"&gt;curl&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;POST&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type: application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{
    "username": "user1",
    "password": "password"
}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="s2"&gt;```

To get a valid JWT in the response and, with it, call our brand new `&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;greet&lt;/span&gt;&lt;span class="s2"&gt;` route:

```&lt;/span&gt;&lt;span class="nx"&gt;bash&lt;/span&gt;
&lt;span class="nx"&gt;curl&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3010/greet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization: Bearer ey...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="s2"&gt;```

And we should receive:

```&lt;/span&gt;
&lt;span class="nx"&gt;Greetings&lt;/span&gt; &lt;span class="nx"&gt;authenticated&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;
&lt;span class="s2"&gt;```

Instead, if we don't provide a valid JWT:

```&lt;/span&gt;&lt;span class="nx"&gt;bash&lt;/span&gt;
&lt;span class="nx"&gt;curl&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3010/greet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;
&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization: This isn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;
```

We should receive an error:

```json
{
    "statusCode": 403,
    "message": "Forbidden resource",
    "error": "Forbidden"
}
```

# Conclusions

We have created two different microservices. Each of them is responsible of different sorts of things. The auth microservice is responsible of the authentication and authorization of the users, and the user microservice is responsible of manage them only.

We could add an endpoint for registering new users in the user microservice or add roles based access to the routes in the auth microservice.

The best part of implementing an approach like this is that we can reuse our auth mechanisms in every new microservice we build. But, on the other hand, if we want to work this way we have to be extremely careful and always keep backwards compatibility in our auth microservice.

# Disclaimer

This post has the purpose of illustrating how to implement the authentication/authorization in a microservices environment, but also doing it in an easy way for making the post readable and enjoyable.

I added here some simplifications and omitted important parts regarding security. Please, if you plan to move this to production, read some articles about how to add security to microservices and best practices about storing secrets and sensible data in production (like passwords, jwt secrets and so...)

If you liked it, don&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="nx"&gt;forget&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;leave&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;:)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>nestjs</category>
      <category>microservices</category>
      <category>typescript</category>
      <category>authentication</category>
    </item>
  </channel>
</rss>
