<?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: Valentin Radu</title>
    <description>The latest articles on DEV Community by Valentin Radu (@rad_val_).</description>
    <link>https://dev.to/rad_val_</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%2F396639%2Fb03c313b-f45a-4b31-8635-49a003fa73b5.jpeg</url>
      <title>DEV Community: Valentin Radu</title>
      <link>https://dev.to/rad_val_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rad_val_"/>
    <language>en</language>
    <item>
      <title>Introducing stencil.email</title>
      <dc:creator>Valentin Radu</dc:creator>
      <pubDate>Tue, 09 Feb 2021 18:55:06 +0000</pubDate>
      <link>https://dev.to/rad_val_/introducing-stencil-email-36fp</link>
      <guid>https://dev.to/rad_val_/introducing-stencil-email-36fp</guid>
      <description>&lt;p&gt;&lt;a href="https://stencil.email"&gt;stencil.email&lt;/a&gt; provides a set of 4 HTML email templates that can be quickly used in just a couple of lines of code.&lt;/p&gt;

&lt;p&gt;All templates are:&lt;br&gt;
✅ Responsive&lt;br&gt;
✅ Customizable (colors, text, icons) &lt;br&gt;
✅ Tested on all major email clients&lt;br&gt;
✅ Ready for production&lt;/p&gt;

&lt;p&gt;I built this because many times I just wanted to send a simple, but good looking, transactional email without having to pollute my workspace with &lt;code&gt;.html&lt;/code&gt; files or rely on hosted third parties. &lt;/p&gt;

&lt;p&gt;This is all you need:&lt;br&gt;
&lt;/p&gt;

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


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stencil&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;Stencil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transactional&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stencil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome, Jane! 🎉&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;We’ve heard you like emails!&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the &lt;a href="https://github.com/valentinradu/stencil"&gt;repo&lt;/a&gt; for examples and the list of customizable features.&lt;/p&gt;

&lt;p&gt;Hope it helps someone out there!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>A remote-only jobs newsletter using NextJS and AWS SES</title>
      <dc:creator>Valentin Radu</dc:creator>
      <pubDate>Sat, 16 Jan 2021 02:56:20 +0000</pubDate>
      <link>https://dev.to/rad_val_/a-remote-only-jobs-newsletter-using-nextjs-and-aws-ses-53om</link>
      <guid>https://dev.to/rad_val_/a-remote-only-jobs-newsletter-using-nextjs-and-aws-ses-53om</guid>
      <description>&lt;p&gt;I decided to start a newsletter a couple of weeks ago and while I never expected a high number of subscribers, I still wanted to avoid unnecessary costs, so I built it from scratch.&lt;/p&gt;

&lt;p&gt;Here's the stack for anyone interested (most are free, open source or with a generous free tier plan)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NextJS&lt;/li&gt;
&lt;li&gt;Vercel (these guys are amazing for small to medium project hosting, as I'm sure many of you already know)&lt;/li&gt;
&lt;li&gt;mjml (email-ready HTML is a pain without it)&lt;/li&gt;
&lt;li&gt;FaunaDB (generous free tier plan, friendly UI)&lt;/li&gt;
&lt;li&gt;AWS SES (it's hard to beat their $0.1 for 1K emails, first 62K free)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;About the newsletter:&lt;/p&gt;

&lt;p&gt;I feel like most of the job postings out there are generic and missing lots of important info:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tools &amp;amp; processes (i.e. &lt;a href="https://teamrank.dev"&gt;teamrank.dev&lt;/a&gt; questions)&lt;/li&gt;
&lt;li&gt;salary (at least a range)&lt;/li&gt;
&lt;li&gt;how long has the position been open&lt;/li&gt;
&lt;li&gt;how many candidates applied (at least an estimate)&lt;/li&gt;
&lt;li&gt;detailed tech stacks&lt;/li&gt;
&lt;li&gt;coworkers expertise and company culture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://startremote.dev"&gt;startremote.dev&lt;/a&gt; is an effort to improve that.&lt;/p&gt;

</description>
      <category>showdev</category>
    </item>
    <item>
      <title>Let's build a simple blockchain</title>
      <dc:creator>Valentin Radu</dc:creator>
      <pubDate>Wed, 25 Nov 2020 19:37:53 +0000</pubDate>
      <link>https://dev.to/rad_val_/let-s-build-a-simple-blockchain-6n3</link>
      <guid>https://dev.to/rad_val_/let-s-build-a-simple-blockchain-6n3</guid>
      <description>&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;How can you trust a data store distributed among an arbitrary number of independent peers? Since each peer has control over its own version of the data, how can you reach a consensus? In a nutshell, these are the main problems blockchain solves.&lt;/p&gt;

&lt;p&gt;The core idea revolves around immutability: once written, the data stored in a blockchain can't be modified without consensus between peers and becomes literally impossible to alter as the transaction gets older (because of the computational cost associated with the proof of work, more about it later on).&lt;/p&gt;

&lt;h1&gt;
  
  
  In layman's terms
&lt;/h1&gt;

&lt;p&gt;Theoretically, you could build a blockchain-like system using only spreadsheets. Each block would be a row and the entire spreadsheet your blockchain. Each row would have a timestamp, some fields where you could store data (e.g. transaction data, account owner, the amount transferred, recipient, etc), a reference to the previous row's hash and the cryptographic hash value of all the fields combined (including the reference field: this puts the chain in the block*chain*).&lt;/p&gt;

&lt;p&gt;I'm assuming you're familiar with cryptographic hashing, if not, there are plenty of resources out there explaining it in various levels of detail (starting with &lt;a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function"&gt;Wikipedia&lt;/a&gt;). Simply put a cryptographic hash function is a one-way function that always produces the same hash value for the same input in a way that makes it impossible (or extremely difficult) to reverse the process (i.e. to find the original input, given the hash value)&lt;/p&gt;

&lt;p&gt;Since all fields get hashed together, any attempt to modify one would automatically result in a different hash value for that specific row.&lt;/p&gt;

&lt;p&gt;So, in order to modify our table and keep the blockchain valid we would have to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;change the row&lt;/li&gt;
&lt;li&gt;recalculate its hash value&lt;/li&gt;
&lt;li&gt;recalculate all the hash values of the subsequent rows since they won't have the correct &lt;em&gt;previous&lt;/em&gt; row hash value anymore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is time-consuming for a human, but nothing for a computer. The hashes can be recalculated in less than a second even for a large blockchain. &lt;/p&gt;

&lt;p&gt;This poses a problem. When picking between two conflicting versions of the chain, the one that required the most computational effort (combined among multiple peers) wins. If chains can be easily altered and recreated the CPU time race turns into a bandwidth race slowing down the entire system. &lt;/p&gt;

&lt;p&gt;That's why blockchain requires proofs of work: computing a hash value might be fast, however, computing a hash value with a certain constraint (e.g. &lt;code&gt;n&lt;/code&gt; leading zeros: normally an SHA hash looks like this &lt;code&gt;979c8b5f0598fec69...&lt;/code&gt;, our constraint would require a new field, the nonce, be tweaked until the hash starts with a certain number of zeros, &lt;code&gt;0000001fb32013...&lt;/code&gt;) requires significantly more time.&lt;/p&gt;

&lt;h1&gt;
  
  
  The best way to learn is by building
&lt;/h1&gt;

&lt;p&gt;The first thing we need to consider is &lt;em&gt;the block&lt;/em&gt;. Like in the spreadsheet example each block has a timestamp, data, and a reference to the previous block. In addition, we have a method to serialize our block (&lt;code&gt;toString&lt;/code&gt; - in a more realistic setup we would also have one to deserialize it), one that calculates the hash based on the current fields, and some setters. Nothing spectacular so far.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Block&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Represents a block
     * @constructor
     * @param {number} timestamp - The timestamp of the block creation
     * @param {data} data - Arbitrary data we wish to store in the block
     * @param {object} prev - A reference to the previous block, if any
     */&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&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;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;assert&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;timestamp&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&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;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Used to update the nounce in order to get a different hash value.
     */&lt;/span&gt;
    &lt;span class="nx"&gt;randomizeNonce&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;nonce&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Calculates the hash of the block based on its string representation
     */&lt;/span&gt;
    &lt;span class="nx"&gt;calculateHash&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;crypto&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&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;update&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;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&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="cm"&gt;/**
     * Once we know the required hash, we seal the block by setting its hash
     * value.
     */&lt;/span&gt;
    &lt;span class="nx"&gt;seal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&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;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Returns the string representation of the block
     */&lt;/span&gt;
    &lt;span class="nx"&gt;toString&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;||&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="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&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;data&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="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nonce&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;Next, we need to create a class responsible for calculating the block's zero prefixed hash. Doing this requires multiple tries and therefore time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Miner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Represents the entity that does the work calculating the required hash for each block.
     * @constructor
     * @param {number} complexity - In our case, the complexity is the requireed number of zeros in front of our hash value. As we increase this value the time and resources needed to compute the hash increases *exponentially*.
     */&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;complexity&lt;/span&gt; &lt;span class="o"&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complexity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;complexity&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;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complexity&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&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="cm"&gt;/**
     * Mining basically means finding a nonce which hashed together with the rest of the fields, the output hash will be prefixed with a number of zeros equal to the complexity.
     */&lt;/span&gt;
    &lt;span class="nx"&gt;mine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&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;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isHashValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;randomizeNonce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calculateHash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;isHashValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&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;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startsWith&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;prefix&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;And finally, the piece that puts everything together. Adding a block to the chain is straightforward enough: we create it using the current timestamp and a reference to our last block, mine its hash then simply replace the last block with our newly created one.&lt;/p&gt;

&lt;p&gt;Things get more interesting in the &lt;code&gt;isValid&lt;/code&gt; method. To validate the entire blockchain we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;go through each block&lt;/li&gt;
&lt;li&gt;check the proof of work by ensuring the hash starts with the given number of zeros&lt;/li&gt;
&lt;li&gt;check the hash (there's a small catch here, when we calculate current hash we also include the previous block's hash and thus validating the link between them)&lt;/li&gt;
&lt;li&gt;finally, when we reach the last block we need to make sure it's the same genesis block as the one we created, otherwise the blockchain could be valid, but it might not be &lt;strong&gt;our&lt;/strong&gt; blockchain.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Blockchain&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * The aggregator that puts everything together
     */&lt;/span&gt;
    &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;genesisBlock&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;Block&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="nx"&gt;now&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;lastBlock&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;genesisBlock&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;miner&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;Miner&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="p"&gt;}&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Adds a new block with the given data
     * @constructor
     * @param {object} data - Arbitrary data
     */&lt;/span&gt;
    &lt;span class="nx"&gt;addBlock&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;block&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;Block&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="nx"&gt;now&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastBlock&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;miner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&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;lastBlock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Checks if the entire blockchain is valid
     */&lt;/span&gt;
    &lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// we start with the last block and while there&lt;/span&gt;
        &lt;span class="c1"&gt;// is a previous block before it &lt;/span&gt;
        &lt;span class="c1"&gt;// (in other words, it's not the genesis block),&lt;/span&gt;
        &lt;span class="c1"&gt;// we check its hash with the value we compute using&lt;/span&gt;
        &lt;span class="c1"&gt;// the current data (possibly tampered) and the previous'&lt;/span&gt;
        &lt;span class="c1"&gt;// block hash&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;block&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;lastBlock&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;miner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isHashValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
                &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;calculateHash&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;false&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// if we reach the last block, we compare it with the &lt;/span&gt;
        &lt;span class="c1"&gt;// genesis block to be sure not only that the blockchain is&lt;/span&gt;
        &lt;span class="c1"&gt;// valid but also that it's **our** blockchain&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;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;genesisBlock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&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;false&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;true&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;And there you have it. Your own toy blockchain. Feel free to give it a spin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blockchain&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;Blockchain&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;quiBlock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;blockchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addBlock&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;Qui-Gon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jedi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obiBlock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;blockchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addBlock&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;Obi-Wan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jedi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// the block should be valid&lt;/span&gt;
&lt;span class="nx"&gt;blockchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// tampering with the data&lt;/span&gt;
&lt;span class="nx"&gt;firstBlock&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;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sith&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// the blockchain is not valid anymore&lt;/span&gt;
&lt;span class="nx"&gt;blockchain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  FAQ
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Where does the data (i.e. the actual bytes) lives?&lt;br&gt;
Blockchain data (e.g. the string representation of each block, one after the other) lives on each of the peers which are actively taking part in the blockchain network. There is no central storage authority/entity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What happens if one peer tries to fraudulently modify the blockchain?&lt;br&gt;
To keep the blockchain valid, it would have to modify the hashes of all the blocks following the one that he alters. That would take a lot of time, depending on the size of the blockchain. Even if it manages to do it somehow, since there are usually many other peers in the network with the blockchain unaltered, the majority would win when reaching consensus. Modifying the blockchain requires control over 50% + 1 of the network and a lot of computing power.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I don't have a distributed network at my disposal, how can I use blockchain technology?&lt;br&gt;
There are lots of options out there like &lt;a href="https://ethereum.org/en/"&gt;the Ethereum project&lt;/a&gt; that allow you to use their network to store arbitrary data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>beginners</category>
      <category>blockchain</category>
      <category>crypto</category>
    </item>
    <item>
      <title>AWS Lambda + Rust</title>
      <dc:creator>Valentin Radu</dc:creator>
      <pubDate>Tue, 10 Nov 2020 17:19:05 +0000</pubDate>
      <link>https://dev.to/rad_val_/aws-lambda-rust-292g</link>
      <guid>https://dev.to/rad_val_/aws-lambda-rust-292g</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was first published on &lt;a href="https://techpilot.dev/article/aws-lambda-rust"&gt;techpilot.dev&lt;/a&gt;&lt;br&gt;
TL;DR: There's an example repo &lt;a href="https://github.com/valentinradu/rust-aws-lambda-example"&gt;here&lt;/a&gt; for those who want to skip the story mode&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.rust-lang.org"&gt;Rust&lt;/a&gt; piqued my interest when I found out it consistently ranked first in the StackOverflow's annual developer survey for the world's most loved programming language. &lt;a href="https://insights.stackoverflow.com/survey/2020#technology-most-loved-dreaded-and-wanted-languages"&gt;Here's&lt;/a&gt; the 2020 survey, but it also holds the first position for 2019, 2018, 2017, and 2016.&lt;/p&gt;

&lt;p&gt;It turns out it's as awesome as they say and now I'm in that particular moment in the hype phase when I try to do everything in Rust. I know that's a terrible idea and I strongly advise against it: pick the language that has the strongest support (aka libraries, community) for the problem you're trying to solve. Doing ML in Rust when Python is de facto standard is not such a great idea.&lt;/p&gt;

&lt;p&gt;Anyways, I figured I can make an exception and since I'm not that excited about any of the popular backend languages, I started to experiment in that direction.&lt;/p&gt;

&lt;p&gt;Running a Rust HTTP server using &lt;a href="https://rocket.rs"&gt;Rocket&lt;/a&gt; is really easy and well documented, however, if you plan to go serverless, there's still a lot of uncharted territories.&lt;/p&gt;

&lt;p&gt;For AWS Lambda, there are a couple of resources out there, but many are outdated or somehow incomplete.&lt;/p&gt;

&lt;p&gt;Here are the main steps we'll have to follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;implement the lambda handlers&lt;/li&gt;
&lt;li&gt;(cross)compile our code for the Amazon Linux platform (x86, 64bit)&lt;/li&gt;
&lt;li&gt;build each lambda as a standalone binary&lt;/li&gt;
&lt;li&gt;configure AWS Lambda for deployment&lt;/li&gt;
&lt;li&gt;deploy &amp;amp; enjoy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, let's get started!&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="c"&gt;# create a new crate&lt;/span&gt;
cargo new rust_aws &lt;span class="nt"&gt;--bin&lt;/span&gt;
&lt;span class="c"&gt;# delete the main.rs, we'll be using a binary for each lambda&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;rust_aws &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm &lt;/span&gt;src/main.rs
&lt;span class="c"&gt;# these are the two lambdas we're going implement&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;src/comment.rs
&lt;span class="nb"&gt;touch &lt;/span&gt;src/contact.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, our dependencies in &lt;code&gt;Cargo.toml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[package]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"your_proj_name"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"You &amp;lt;you@example.com&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;edition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"2018"&lt;/span&gt;

&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;lambda_runtime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.1"&lt;/span&gt;
&lt;span class="py"&gt;lambda_http&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.1"&lt;/span&gt;
&lt;span class="nn"&gt;tokio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^0.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;["full"]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nn"&gt;[[bin]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"comment"&lt;/span&gt;
&lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"src/comment.rs"&lt;/span&gt;

&lt;span class="nn"&gt;[[bin]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"contact"&lt;/span&gt;
&lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"src/contact.rs"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A couple of things to mention here. &lt;br&gt;
First, we have the &lt;code&gt;lambda_runtime&lt;/code&gt; and &lt;code&gt;lambda_http&lt;/code&gt; crates which are responsible for communicating with the Lambda API. This usually means running the setup code, fetching the handler name from an environment variable, and passing events to our code. You can find out more about how custom runtimes work &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Although lambdas are stateless, AWS can run our binaries and send multiple events to the same process, as long as the process doesn't exit. This requires an event loop: a fancy way to handle asynchronous I/O and scheduling. We use &lt;a href="https://tokio.rs"&gt;tokio&lt;/a&gt; for that.&lt;/p&gt;

&lt;p&gt;Finally, we declared 2 different binaries, one named &lt;code&gt;comment&lt;/code&gt;, the other &lt;code&gt;contact&lt;/code&gt; and each will be deployed as a standalone lambda function&lt;/p&gt;

&lt;p&gt;Next up, compilation. Unless you're on an x86, 64bit Linux machine, you'll have to cross-compile your code. To do so, we need the correct toolchain:&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="c"&gt;# adds the x86 64 target to the toolchain&lt;/span&gt;
rustup target add x86_64-unknown-linux-musl
&lt;span class="c"&gt;# installs the x86 64 toolchain on macOS (for Windows, you can probably do it with cygwin-gcc-linux, but I haven't tried it out)&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;FiloSottile/musl-cross/musl-cross
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we need to let &lt;code&gt;cargo&lt;/code&gt; know we're cross-compiling: add the following in &lt;code&gt;./.cargo/config.toml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[target.x86_64-unknown-linux-musl]&lt;/span&gt;
&lt;span class="py"&gt;linker&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"x86_64-linux-musl-gcc"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we're ready to compile. &lt;code&gt;cargo build --target x86_64-unknown-linux-musl&lt;/code&gt; to test it out.&lt;/p&gt;

&lt;p&gt;The next thing we need to do is to configure &lt;a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html"&gt;SAM&lt;/a&gt;. I'll assume you're already familiar with SAM and focus only on the critical section for our case. You can have a look at the full &lt;code&gt;template.yml&lt;/code&gt; in the example repository. Also,  skip &lt;code&gt;sam init&lt;/code&gt; since there is no Rust template available anyhow (to my knowledge)  and simply start with the &lt;code&gt;template.yml&lt;/code&gt; file and build your own directory structure.&lt;/p&gt;

&lt;p&gt;Let's go through the one of the lambdas' definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# template.yml&lt;/span&gt;
&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Serverless::Function&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;FunctionName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Comment&lt;/span&gt;
    &lt;span class="na"&gt;Handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;doesnt.matter.the.runtime.is.custom&lt;/span&gt;
    &lt;span class="na"&gt;Runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provided&lt;/span&gt;
    &lt;span class="na"&gt;MemorySize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;128&lt;/span&gt;
    &lt;span class="na"&gt;Timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="na"&gt;CodeUri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="na"&gt;Policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;AWSLambdaBasicExecutionRole&lt;/span&gt;
    &lt;span class="na"&gt;Events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;comment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Api&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/comment&lt;/span&gt;
    &lt;span class="na"&gt;Method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;post&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells SAM to create a lambda serverless function named &lt;code&gt;Comment&lt;/code&gt;, with a custom runtime (handled by or Rust &lt;code&gt;lambda_runtime&lt;/code&gt;) and expose it as a REST API resource at &lt;code&gt;/comment&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We're almost done. One last (important) thing: when we build and deploy our lambdas with &lt;code&gt;sam build &amp;amp;&amp;amp; sam deploy --guided&lt;/code&gt; SAM will look for a &lt;code&gt;Makefile&lt;/code&gt; since it doesn't know how to build our project by itself.&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="nb"&gt;touch &lt;/span&gt;Makefile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nl"&gt;build-Comment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    cargo build &lt;span class="nt"&gt;--bin&lt;/span&gt; comment &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--target&lt;/span&gt; x86_64-unknown-linux-musl
    &lt;span class="nb"&gt;cp&lt;/span&gt; ./target/x86_64-unknown-linux-musl/release/comment &lt;span class="nv"&gt;$(ARTIFACTS_DIR)&lt;/span&gt;/bootstrap

&lt;span class="nl"&gt;build-Contact&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    cargo build &lt;span class="nt"&gt;--bin&lt;/span&gt; contact &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--target&lt;/span&gt; x86_64-unknown-linux-musl
    &lt;span class="nb"&gt;cp&lt;/span&gt; ./target/x86_64-unknown-linux-musl/release/contact &lt;span class="nv"&gt;$(ARTIFACTS_DIR)&lt;/span&gt;/bootstrap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The way this works is straightforward, you need to add a target for each lambda name and prefix it with &lt;code&gt;build-&lt;/code&gt;.  That's it. SAM will invoke them as needed.&lt;br&gt;
Each target builds the respective binary (&lt;code&gt;--bin contact&lt;/code&gt;) and copies it in the artifacts directory, where it will be zipped and sent to the AWS servers for deployment.&lt;/p&gt;

&lt;p&gt;And that's it. We're done. Have fun with your new Rust-powered AWS lambdas!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>rust</category>
      <category>aws</category>
      <category>backend</category>
    </item>
    <item>
      <title>How to spot a great team during interviews</title>
      <dc:creator>Valentin Radu</dc:creator>
      <pubDate>Sat, 31 Oct 2020 00:02:23 +0000</pubDate>
      <link>https://dev.to/rad_val_/how-to-spot-a-great-team-during-interviews-53h2</link>
      <guid>https://dev.to/rad_val_/how-to-spot-a-great-team-during-interviews-53h2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I've published this article on my blog in April, and it ultimately led to &lt;a href="https://teamrank.dev"&gt;teamrank.dev&lt;/a&gt;, an app that ranks teams based on ideas presented here. Feel free to try it out and share your results!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How?! Well, by asking the right questions! 😁 &lt;br&gt;
While at &lt;a href="https://techpilot.dev"&gt;techpilot.dev&lt;/a&gt; I've had my fair share of interviews, and although I've heard the most intriguing answers to the technical questions, one thing was always the same: it seems very few really want to know more about the team they might join in the future. 😅 &lt;/p&gt;

&lt;p&gt;I think it's a wasted opportunity, so here are a few ideas on what to ask.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do they manage requirements and feature specs?&lt;/li&gt;
&lt;li&gt;What tools do they use in the process?&lt;/li&gt;
&lt;li&gt;Who is writing the specs? (i.e. there should definitely be someone and the answer should be prompt)&lt;/li&gt;
&lt;li&gt;Is the release process well defined?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Issues and bug management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are bugs fixed before writing new code?&lt;/li&gt;
&lt;li&gt;Where and how do they track bugs and issues? &lt;/li&gt;
&lt;li&gt;How do they prioritize and sort bugs? Who does that?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who's doing the manual/integration testing? (e.g. ideally a designated tester)&lt;/li&gt;
&lt;li&gt;Does the project have unit tests? What's their coverage?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Release cycle and automation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do they use CI? If so, how's the setup?&lt;/li&gt;
&lt;li&gt;What tools do they use? (e.g. Jenkins, Github Actions, etc)&lt;/li&gt;
&lt;li&gt;Do they build a daily/nightly version?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Growth&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If hired, will you have a mentor or a person that can help you with your career path?&lt;/li&gt;
&lt;li&gt;Do they review code? At what point in the development lifecycle? Who does it (i.e. peer, lead, etc)&lt;/li&gt;
&lt;li&gt;Do they have a library or do they buy tech books for their employees?&lt;/li&gt;
&lt;li&gt;Will there be any opportunities for greenfield projects shortly? (starting a project can be challenging, but also a great way to learn things!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workspace&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is it quiet?&lt;/li&gt;
&lt;li&gt;How crowded is it?&lt;/li&gt;
&lt;li&gt;What equipment does each dev get (in general look for companies which understand that equipment affects your productivity)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Codebase, frameworks, and tools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How old is the project? (the older, the greater the chance it's messy)&lt;/li&gt;
&lt;li&gt;What stack and tools do they use? (keep in mind you want a job where you fit or one that you can easily adapt to, so even opinionated views matter)&lt;/li&gt;
&lt;li&gt;Did they adopt a coding style? If yes, do they enforce it with a linter?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Team&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How large is the team you're going to be part of if hired?&lt;/li&gt;
&lt;li&gt;Who else shares similar responsibilities? (i.e. you want to avoid 1-man teams unless you know exactly what you're doing)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if you're feeling bold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask how did they solve a particular task or architectural problem that you have previous experience with (e.g. "How do services communicate with each other?", "How are the private keys stored securely?", etc)&lt;/li&gt;
&lt;li&gt;Ask about the current team members' backgrounds. Make it clear you're not looking for personal information, but you're interested in the team maturity and experience (things like years in the field, areas of expertise, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, here are some things to avoid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't ask about things you're not genuinely interested in. Be frank and to the point. A never-ending interview can also mean a predisposition to never-ending meetings. (on both sides)&lt;/li&gt;
&lt;li&gt;Generic, mindless, low-effort questions. Although HR might like it, in a technical interview is best to avoid them and be spot on instead. Things like "How does your team approach problems in general?" "Are there opportunities for professional development?" should have an answer in the more detailed questions above. Asking them directly doesn't help anybody. Is like asking "Is this job good?". "Yes!". "Ok, that's all I wanted to know!".&lt;/li&gt;
&lt;li&gt;Personal details. You might think it would set a more familiar and relaxed tone, however, people have different views on it, and assuming otherwise is gambling with your chances: you might win, but you might also lose.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>interviewing</category>
    </item>
    <item>
      <title>A practical guide to microservices</title>
      <dc:creator>Valentin Radu</dc:creator>
      <pubDate>Wed, 10 Jun 2020 14:57:35 +0000</pubDate>
      <link>https://dev.to/rad_val_/a-practical-guide-to-microservices-3nf3</link>
      <guid>https://dev.to/rad_val_/a-practical-guide-to-microservices-3nf3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;First published on &lt;a href="https://techpilot.dev/article/a-practical-guide-to-microservices"&gt;techpilot.dev&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Microservices are the natural evolution of monolithic systems in an increasingly demanding, modular, and distributed industry. The strongest argument against them is usually the implied complexity, debugging, and deployment challenges coupled with the poor development experience for small teams/projects.&lt;/p&gt;

&lt;p&gt;In practice, most of these problems come from &lt;em&gt;suboptimal implementations&lt;/em&gt;, not from the architectural pattern itself. There's &lt;em&gt;still&lt;/em&gt; lots of confusion around microservices. Almost every time I bring the topic up, I find someone with a new, unique understanding of it. So, here's my (opinionated) attempt at debunking some of these myths and hopefully help you navigate these stormy waters.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Take it step by step&lt;/strong&gt;. Between a seemingly steep learning curve and the multitude of overlapping tools and frameworks out there, things can quickly become overwhelming&lt;br&gt;
Evolve your architecture using only tools that solve &lt;em&gt;the problems you know you have&lt;/em&gt;, not problems you might think you'll have at a one point. &lt;br&gt;
It's perfectly fine to start with a "monolith": all actors in one place, but try to design it in such a way that it won't require a tremendous amount of effort to migrate each actor in its own process. &lt;br&gt;
To achieve this, use standard best practices: inject dependencies, favour composition over inheritance, have a test-driven approach, encapsulate external dependencies etc. I'd argue that by adding a messaging queue to a well designed, modular "monolith" automatically turns it into microservices. Which takes us to our next topic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use a messaging queue right from the start.&lt;/strong&gt; Using a messaging queue, something as simple as &lt;a href="https://redis.io"&gt;Redis&lt;/a&gt; pubsub or as sophisticated as &lt;a href="https://www.rabbitmq.com"&gt;RabbitMQ&lt;/a&gt; will allow you to draw hard lines between your components and stop caring if they run in the same process, on the same machine or even in the same data center. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Draw seams based on the problem domain&lt;/strong&gt; What is a microservice after all? Where do we draw the line between units in our system? Is paramount that the answer to these questions is problem domain-driven. Don't expect a certain count or size, just split them however comes natural for the problem you're trying to solve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid breaking-up your components too early&lt;/strong&gt; Your enemies here are boilerplate code and lack of domain knowledge. Lay down strong foundations using the best practices you already know and let your system grow. &lt;br&gt;
When you start a new project you usually don't have enough domain knowledge to correctly define your seams. Breaking-up your system into too many parts early will result in lots of boilerplate code for little functionality. &lt;br&gt;
Start small, grow steady. For example, an online store, could only have 4 microservices in its first iteration: account, payments, orders and notifications. Later as your solution matures, you could add inventory, affiliates, tracking, suggestions and so on. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validate both the input and the output of each microservice&lt;/strong&gt; You should reason about each unit of your system in isolation. This is not necessary microservices related, it's architectural 101. Each unit will have an API, a set of functions and capabilities exposed to its peers. Its input and output should always be validated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Develop and debug in-process&lt;/strong&gt; As much as possible try to take architectural decisions that don't impair your ability to load all your microservices in a debugger within the same process if needed. This is priceless for development speed and bugfixing. &lt;br&gt;
One of the traditional advantage of microservices is the ability to use different technology stacks for various parts of your system, but this comes with a high price, use it wisely. Having a cohesive development and debugging process is much more important, especially for a small team or solo developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't let the persistence layer drive your architecture&lt;/strong&gt; There's a misconception that you have to choose between sharing a database among your microservices and have database per microservice. In truth, it doesn't matter, the only thing that matters is that each microservice owns its data store. That means, two microservice should never query or reference the same data store. You can achieve this in many ways, but some make it harder to brake the rules we mentioned above, like having a microservice per database, or per schema (which is what I usually prefer, since it's a design that allows you to deploy both on the same and different database).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Replicate data to completely separate data stores&lt;/strong&gt; Lets imagine we have an online store that has an account and order component, among others. As we learned earlier, the data stores of these two should be owned by each. However, the order needs to know its owner (aka the entity who place it), so how should we approach this?&lt;br&gt;
In a monolith this would be a foreign key in database, but this breaks the ownership rule, the order service's database should not reference the account's id since they might not even be on the same machine. &lt;br&gt;
One elegant way to solve this problem is using data replication. The order's database could have one table only with unique owners ids. These would be populated by events in your system: every time a new user is added the account microservice broadcasts their ids and the order microservice (and probably others too) adds them to the owners manifest.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authorize using JWT and similar technologies&lt;/strong&gt; The simplest way to handle authentication/authorization is to skip the central authority and use technologies like JWT to verify claims without leaving the process (or without calling another microservice). There are many options here and it really depends on the security level your apps requires, but in general for highest security each microservice should check the authorization and permissions before doing anything, no matter how small, while for convenience this can be done at the gateway level only (aka in the component that exposes the public API). I usually go with the former since I think the added security justifies the small overhead of locally checking the identity each time.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You don't have to deploy using Docker or Kubernetes right from the start&lt;/strong&gt; Don't get me wrong, these are great technologies, but both add another layer of complexity to your app. You should consider learning them based on the return of investment rule: does the added complexity and time spent on learning these tools justifies the advantages? Unfortunately, this is a bit difficult to answer. That's why it think it's better to start small.&lt;br&gt;
If your project uses a popular stack, one of the PaaS out there (e.g. &lt;a href="https://heroku.com"&gt;Heroku&lt;/a&gt;) is probably a much better fit. There's a strong tendency of overcomplicating things when it comes to microservices deployment. &lt;br&gt;
Don't forget, microservices are an architectural pattern than can be used no matter how or where you're deploying your app. Your ultimate goal should be to have a clean, scalable solution that doesn't require disproportional effort to build and maintain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitor your cluster&lt;/strong&gt; Logging and monitoring helps you find issues early and react accordingly.&lt;br&gt;
Avoid third-party or self-made realtime logging libraries (aka you should never make an in-process remote request to log things). Simply log everything using stderr and stdout (with something as simple as &lt;a href="https://github.com/visionmedia/debug"&gt;debug&lt;/a&gt;), then aggregate your logs. If you're using a PaaS, this last step might be already done for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing is a must&lt;/strong&gt; Write unit test, write integration tests, write end to end tests. In inverse order of their magnitude (i.e. unit tests should come in the largest number). Also, each bug you ever find should have corresponding unit test. With microservices unit testing is not optional, you will never be able to reason about your system as a whole if you can reason about it in isolation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>microservices</category>
      <category>node</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Are unit tests a waste of your time?</title>
      <dc:creator>Valentin Radu</dc:creator>
      <pubDate>Sun, 07 Jun 2020 22:36:00 +0000</pubDate>
      <link>https://dev.to/rad_val_/are-unit-tests-a-waste-of-your-time-5al0</link>
      <guid>https://dev.to/rad_val_/are-unit-tests-a-waste-of-your-time-5al0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;First published on &lt;a href="https://techpilot.dev/article/are-unit-tests-a-waste-of-time"&gt;techpilot.dev&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;TL;DR In a perfect world, we would have automated tests for everything, but in reality, there's always a compromise between code quality and costs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've been lucky enough to start a fair amount of greenfield projects in the past years. Looking back, I feel like writing tests had always saved time in the long run but were rather cumbersome when working on UI and smaller projects.&lt;/p&gt;

&lt;p&gt;It goes without saying that for some apps (i.e. life-critical, mission-critical) an unit test coverage of 80%+ should be required. But, despite what most of the literature says, in some cases, unit tests are actually slowing us down. In which case, how do we decide if it's worth the trouble and keep a balance between quality and costs?&lt;/p&gt;

&lt;p&gt;Here are a couple of things to consider.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Debugging process&lt;/strong&gt; Remember when you had that one awkward bug, and it took days only to reliably reproduce it? Unit tests allow you to control the state of your components in great detail, making it easier to find and fix such issues. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusability and life span&lt;/strong&gt; If you wrapped up some code in a reusable library, chances are you'll improve it frequently in the beginning. Unit tests can help you ensure no breaking changes sneak through each iteration. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt; When you can't reason about a system in the wild, it helps to frame it in isolation. Unit tests do just that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third-party dependencies&lt;/strong&gt; Software requires the perfect alignment of many moving parts, some of them not under your control. When third parties act unexpectedly, it becomes almost impossible to debug your system. Mocking dependencies in your unit tests solves this. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Costs&lt;/strong&gt; If you think you don't have enough time to write unit tests it automatically means you're ready to trade quality for it. This might work in some scenarios (e. g. proof of concepts), but you must be aware of the implications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team size&lt;/strong&gt; You'll find that as you make your code testable, you also increase its intrinsic quality. Also, unit tests are the closest thing to written specs, and while you can manage without any formal requirements while working on a part-time project by yourself, larger, heterogeneous teams would have a hard time doing so.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unit testing is time-consuming, especially if you have a poorly designed codebase. You can decide to skip it, and it might be the right thing to do, depending on the context, but you'll have to trade code quality in return.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>bestpractices</category>
      <category>teamleading</category>
    </item>
  </channel>
</rss>
