<?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: Chris Gregori</title>
    <description>The latest articles on DEV Community by Chris Gregori (@chriis).</description>
    <link>https://dev.to/chriis</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%2F142317%2F69029546-87e4-4746-93cc-d3ae7f54a321.jpg</url>
      <title>DEV Community: Chris Gregori</title>
      <link>https://dev.to/chriis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chriis"/>
    <language>en</language>
    <item>
      <title>10 tips for new Elixir developers</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Tue, 12 Jul 2022 10:43:19 +0000</pubDate>
      <link>https://dev.to/chriis/10-tips-for-new-elixir-developers-48jl</link>
      <guid>https://dev.to/chriis/10-tips-for-new-elixir-developers-48jl</guid>
      <description>&lt;p&gt;Elixirs popularity has exploded in the last year - and for good reason! &lt;/p&gt;

&lt;p&gt;Stack Overflows 2022 Developer Survey lists Phoenix as &lt;em&gt;the most &lt;a href="https://survey.stackoverflow.co/2022/#section-most-loved-dreaded-and-wanted-web-frameworks-and-technologies"&gt;most loved Web framework&lt;/a&gt;&lt;/em&gt; and Elixir is now &lt;a href="https://survey.stackoverflow.co/2022/#section-most-loved-dreaded-and-wanted-web-frameworks-and-technologies"&gt;the sixth highest paid language&lt;/a&gt; 👀 - it might be time to have a look if you haven't already.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Elixir?
&lt;/h2&gt;

&lt;p&gt;It's a dynamic, functional programming language with an emphasis on fault tolerance, scalability, and developer experience. &lt;strong&gt;It's gorgeous.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm fortunate enough to write Elixir daily (when I'm not in meetings) as part of my job as the core tech stack and have done so for over 3 years. As such I've encountered some of the gotchas you're likely to experience if you're new to the language and amassed a bank of helpful tips to ensure you're really getting the most out of the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Get used to pattern matching
&lt;/h2&gt;

&lt;p&gt;In Elixir, the &lt;code&gt;=&lt;/code&gt; operator is actually the match operator. You can use it to assign variables just as you might expect but its hidden power comes from its ability to destructure complex data types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A quick example from the official language guide:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="ss"&gt;:hello&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="s2"&gt;"world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this is all well and good but some of the real fun comes from pattern matching on function heads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace pesky &lt;code&gt;if&lt;/code&gt; statements
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;first_name:&lt;/span&gt; &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Greetings, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Greetings, stranger!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Handle different outcomes in your code declaritively
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;split_traffic&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;users_age&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_age&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# redirect to path A&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;split_traffic&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;users_age&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_odd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_age&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# redirect to path B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Append to a list the correct way
&lt;/h2&gt;

&lt;p&gt;Lists in Elixir are effectively linked lists - they are internally represented in pairs containing the head and the tail of a list. &lt;/p&gt;

&lt;p&gt;Meaning both of these approaches are valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;list&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="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[]]]]&lt;/span&gt;
&lt;span class="c1"&gt;# [1, 2, 3]&lt;/span&gt;
&lt;span class="n"&gt;list&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="c1"&gt;# [1, 2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because of their linked list nature, prepending to a list is always faster (as it's constant time vs having to internally traverse each list til the end and append - linear time).&lt;/p&gt;

&lt;p&gt;You can add to them by concatenating lists together using &lt;code&gt;Kernal.++/2&lt;/code&gt; or you can use &lt;code&gt;|&lt;/code&gt; to do the same thing &lt;em&gt;faster&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Have a look at the example below (which is using the erlang timer module to time the function call).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&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="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="n"&gt;iex&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="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&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="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&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="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="o"&gt;++&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="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&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="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="o"&gt;++&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="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&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="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:timer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;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="o"&gt;++&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="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Finding N slowest tests in mix application
&lt;/h2&gt;

&lt;p&gt;You'll be writing tests in your Elixir code (&lt;em&gt;right?&lt;/em&gt; 🙏🏼), and once your application grows to a large size you may find your tests take a long time to execute (not too long, Elixir's pretty speedy). &lt;/p&gt;

&lt;p&gt;You can narrow the culprits down with the following:&lt;br&gt;
&lt;code&gt;mix test --slowest N  # prints timing information for the N slowest tests&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Read the docs (especially Enum)
&lt;/h2&gt;

&lt;p&gt;This might be an obvious one to many of you but you'd be surprised how often people don't &lt;a href="https://en.wikipedia.org/wiki/RTFM"&gt;RTFM&lt;/a&gt;. I actually discovered that last tip by reading the official docs 🤯 - Elixir's documentation and standard libraries are stellar. &lt;/p&gt;

&lt;p&gt;I can guarentee that you'll be using the &lt;code&gt;Enum&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;List&lt;/code&gt;, and  &lt;code&gt;Kernal&lt;/code&gt; modules often - get used to reading their documentation. &lt;/p&gt;

&lt;p&gt;You'll find examples like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Enum.chunk_while/2&lt;/code&gt; for chunking lists when certain conditions are met&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Enum.into/2&lt;/code&gt; for converting enumerables into collectables (lists into maps)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Map.put_new_lazy/3&lt;/code&gt; for putting the result of a function into a key if it's not already there&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any time you think there's a more functional way to do something - there probably is, get reading, chances are the standard librarys got you.&lt;/p&gt;

&lt;p&gt;This leads me on to my next point quite nicely...&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Embrace Doctests
&lt;/h2&gt;

&lt;p&gt;It's impossible to talk about how good Elixirs documentation is without talking about the magic of doctests. I've spoken about these before in my &lt;a href="https://chrisgregori.substack.com/p/elixirs-hidden-potions-664814640969"&gt;Elixirs Hidden Potions post&lt;/a&gt; (which you should also read) but I have to re-iterate just how powerful this can be.&lt;/p&gt;

&lt;p&gt;Doctests let you annotate your functions with example usage (including expected output) and have them run as part of your test suite. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26ufdipQqU2lhNA4g/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26ufdipQqU2lhNA4g/giphy.gif" alt="Wow" width="200" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, they're as amazing as they sounds.&lt;/p&gt;

&lt;p&gt;Taken from the official &lt;a href="https://elixir-lang.org/getting-started/mix-otp/docs-tests-and-with.html"&gt;getting started guide&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;KVServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Command&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@doc&lt;/span&gt; &lt;span class="sx"&gt;~S""&lt;/span&gt;&lt;span class="s2"&gt;"
  Parses the given `line` into a command.

  ## Examples

      iex&amp;gt; KVServer.Command.parse("&lt;/span&gt;&lt;span class="no"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;shopping&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;\&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="s2"&gt;")
      {:ok, {:create, "&lt;/span&gt;&lt;span class="n"&gt;shopping&lt;/span&gt;&lt;span class="s2"&gt;"}}

  """&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:not_implemented&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Running the tests...&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="no"&gt;KVServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&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="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="no"&gt;KVServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;CommandTest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;kv_server&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;command_test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="ss"&gt;exs:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
     &lt;span class="no"&gt;Doctest&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;
     &lt;span class="ss"&gt;code:&lt;/span&gt; &lt;span class="no"&gt;KVServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="s2"&gt;"CREATE shopping&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:create&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"shopping"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
     &lt;span class="ss"&gt;lhs:&lt;/span&gt;  &lt;span class="ss"&gt;:not_implemented&lt;/span&gt;
     &lt;span class="ss"&gt;stacktrace:&lt;/span&gt;
       &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;kv_server&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="ss"&gt;ex:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;KVServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Command&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Atoms are not garbage collected
&lt;/h2&gt;

&lt;p&gt;Be careful about converting user supplied parameters and converting them into atoms. Atoms are meant to be used as named constants - do not take parameters from your users and convert them into atoms. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atoms are not garbage collected.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The reason for this is because Atoms are represented as integers internally - when Beam (the Erlang VM) sees an atom for the first time, it inserts it into the atom table. &lt;/p&gt;

&lt;p&gt;Don't worry - when your code is littered with &lt;code&gt;:ok&lt;/code&gt; atoms from tuples they're all referencing the same atom (the one referenced from your atom table).&lt;/p&gt;

&lt;p&gt;If you really, for some reason, need to convert user generated data into atoms - reach for &lt;code&gt;String.to_existing_atom/1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Fun fact: the default maximum number of atoms is &lt;code&gt;1048576&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Embrace the small, but mighty community
&lt;/h2&gt;

&lt;p&gt;Elixir isn't the biggest language (yet  😏) but it has one of the most helpful communities I've ever stumbled across. &lt;/p&gt;

&lt;h3&gt;
  
  
  Slack
&lt;/h3&gt;

&lt;p&gt;I'm consistently being assisted by the creators of platforms, libraries, &lt;strong&gt;the language itself&lt;/strong&gt; all on the Elixir Slack channel. Get involved and do your part answering questions you can help with as they pop up. &lt;/p&gt;

&lt;h3&gt;
  
  
  Twitter
&lt;/h3&gt;

&lt;p&gt;Some people hate Twitter - I maintain that it's a treasure trove of great information if you're willing to curate your feed and block out the noise. &lt;/p&gt;

&lt;p&gt;Some of my favourite Elixir twitter accounts to follow include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/josevalim/"&gt;Jose Valim - the creator of Elixir&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/chris_mccord"&gt;Chris McCord - the creator of Phoenix &amp;amp; LiveView&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/ukutaht"&gt;Uku Täht - Founder of Plausible Analytics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/codestirring"&gt;Chris Gregori 😉 - Founder of niceice.io &amp;amp; 6words.xyz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/joladev"&gt;Johanna Larson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/evadne"&gt;Evadne W&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I've left you out &lt;a href="https://www.twitter.com/codestirring"&gt;send me a message on Twitter&lt;/a&gt; and I'll add you to the list!&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Add labels to your IO.inspect/2 calls
&lt;/h2&gt;

&lt;p&gt;Really you should be using Pry for debugging your applications (see more in my other article here), but sometimes you just need a quick and dirty way to print out and that's where &lt;code&gt;IO.inspect&lt;/code&gt; comes in.&lt;/p&gt;

&lt;p&gt;The thing is you may get lost in the sea of terminal print out when you're trying to debug lots of data that looks very similar. &lt;/p&gt;

&lt;p&gt;Consider the following pseudo-code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;customer_orders&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;validate_purchases&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="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;exclude_late_orders&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="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;email_customers&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your &lt;code&gt;customer_orders&lt;/code&gt; represented a complicated schema with lots of nested data (and many of them) you'd struggle to decipher which are which in your printed logs after transformation - a simple option being passed to our IO.inspect/2 calls makes this inspection a hell of a lot more legible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;customer_orders&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;validate_purchases&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="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;label:&lt;/span&gt; &lt;span class="s2"&gt;"Validated purchases"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;exclude_late_orders&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="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;label:&lt;/span&gt; &lt;span class="s2"&gt;"On-time orders"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;email_customers&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Try and keep your functions small and composable
&lt;/h2&gt;

&lt;p&gt;This is a tip that applies to most software disciplines also.&lt;/p&gt;

&lt;p&gt;When I first stumbled across functional programming, one thing that took some getting used to was creating lots of little functions. I used to write a lot of React - and thus a fair amount of boilerplate - which meant that I was used to large render functions. &lt;/p&gt;

&lt;p&gt;In Elixir, and all functional programming, try and create lots of small function calls to describe your code. There are plenty of benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's more declarative so it's easier to read and reason about&lt;/li&gt;
&lt;li&gt;It's easier to refactor later on down the line&lt;/li&gt;
&lt;li&gt;It's easier to test&lt;/li&gt;
&lt;li&gt;It helps enforces the DRY principle&lt;/li&gt;
&lt;li&gt;If you structure your code nicely you'll find that you'll re-use plenty of functions often which inadvertently leads to better code structure. Better code structure also leads less circular dependency referencing which leads to faster compile times (but this is a topic for another blog post - let me know if you'd like to hear more!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. Learn about Macros but be cautious
&lt;/h2&gt;

&lt;p&gt;Macros are powerful - with great power comes great ~responsibility~ chance of doing something invisible and horrendous to your codebase. Even &lt;a href="https://elixir-lang.org/getting-started/meta/macros.html"&gt;the official language docs&lt;/a&gt; tell you to use them responsibly. &lt;/p&gt;

&lt;p&gt;You can use macros to extend module behaviour by adding functionality through wrappers - think along the lines of always logging when you call a function without having to declare it - or dynamically generating routes in your Phoenix application to warn a developer when they've not accounted for something they should've like localisation. &lt;/p&gt;

&lt;p&gt;It's good to be aware of Macros and what they can do for you - but seriously, triple check yourself every time you think about adding one. If you want a custom guard clause for your function heads pattern matching, look at &lt;code&gt;defguard&lt;/code&gt; and &lt;code&gt;defguardp&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;There we have it.&lt;/p&gt;

&lt;p&gt;10 tips to help you embark upon your Elixir journey. It's an incredible language, give it a chance and you'll slowly realise why I've been hooked for the past 3 years. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://chrisgregori.substack.com/"&gt;Subscribe to my Substack&lt;/a&gt; for similar content and &lt;a href="https://www.twitter.com/codestirring"&gt;follow me on Twitter&lt;/a&gt; for more Elixir (and general programming) tips.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>5 scary Git commands you'll eventually have use for</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Fri, 08 Jul 2022 10:43:49 +0000</pubDate>
      <link>https://dev.to/chriis/5-scary-git-commands-youll-eventually-have-use-for-42f2</link>
      <guid>https://dev.to/chriis/5-scary-git-commands-youll-eventually-have-use-for-42f2</guid>
      <description>&lt;p&gt;Version control is magical.&lt;/p&gt;

&lt;p&gt;I strongly believe everyone should learn how to use it - not just developers. How many times did you complete homework back at school and create arrays of filenames to denote just how final that piece of work was?&lt;/p&gt;

&lt;p&gt;Today, in modern web development, Git is an absolute pre-requisite. But it's still shocking to see just how many experienced developers are just scratching the surface of what Git can do for you.&lt;/p&gt;

&lt;p&gt;In this blog post I hope to unearth at least one useful Git command you perhaps haven't come across or would even think to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  git rebase
&lt;/h2&gt;

&lt;p&gt;Git rabasing is boils down to moving or combining a sequence of commits into a new base commit. It essentially appears like you've created your branch from a different commit base - extremely useful if you've been working on a branch for a while, you've diverged off of the main branch for a while and you run into conflicts when you try and merge back in.&lt;/p&gt;

&lt;p&gt;It works something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main &lt;span class="c"&gt;# change to main branch&lt;/span&gt;
git pull origin main 
git checkout - &lt;span class="c"&gt;# go back to last branch (feature branch)&lt;/span&gt;
git rebase main
&lt;span class="c"&gt;# fix conflicts&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git rebase &lt;span class="nt"&gt;--continue&lt;/span&gt; &lt;span class="c"&gt;# until all changes are in&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use &lt;code&gt;--interactive&lt;/code&gt; mode for rebasing which will let you manually select which commits you want to ignore throughout - helpful if you've made a commit purely to add some debugging and forgotten before committing. &lt;/p&gt;

&lt;p&gt;Now, some of you might be thinking you can just &lt;code&gt;git pull origin main&lt;/code&gt; in your branch and resolve the merge conflicts &lt;em&gt;in an even easier fashion&lt;/em&gt;. While they are both similar there's one massive difference that you want to keep in mind here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git pull&lt;/code&gt; will create a new commit that combines the two branches together&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git rebase&lt;/code&gt; will move the commits of one branch on top of the other&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also use &lt;code&gt;git pull --rebase&lt;/code&gt; to pull using rebase which can be great and save you a lot of time. However&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git rebase&lt;/code&gt; will essentially keep your git history clean. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is this important?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;It means you can safely and effectively use our next arcane power: &lt;code&gt;git bisect&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  git bisect
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;git bisect&lt;/code&gt; uses binary search to find a commit that introduced some new unwanted functionality (read: bug). &lt;/p&gt;

&lt;p&gt;It kind of works like this:&lt;/p&gt;

&lt;p&gt;Imagine you're digging for the commit that broke a feature that we knew was working in commit &lt;code&gt;0cd429f02&lt;/code&gt; (or a tagged commit), and somewhere along the way we broke something and a test is failing. &lt;/p&gt;

&lt;p&gt;We can use git bisect to narrow down the commits and help us identify the culprit like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git bisect start
git bisect bad
git bisect good 0cd429f02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note: You can use &lt;code&gt;git bisect reset&lt;/code&gt; to jump out of this.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you've specified a good and a bad commit, bisect will find a commit in the middle of that range, check it out and give you some information regarding how many possible steps are left to split through.&lt;/p&gt;

&lt;p&gt;Now that you're in your checked out commit you should run your tests and assuming it works, you can inform bisect of that by typing &lt;code&gt;git bisect good&lt;/code&gt;, or tell bisect that that particular version is failing with &lt;code&gt;git bisect bad&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Repeat the above steps and eventually you'll run out of revisions to test - bisect will then spit out the description of the first bad commit with a nice little summary - and there's your buggy commit. ✨&lt;/p&gt;

&lt;h2&gt;
  
  
  git stash
&lt;/h2&gt;

&lt;p&gt;Stashing is used to take your uncommitted changes (including staged) and temporarily "stash" them away for later. &lt;/p&gt;

&lt;p&gt;Extremely useful when you're not quite ready to commit a change, but need to move to another branch for some reason - maybe there's a bug you need to investigate. &lt;/p&gt;

&lt;p&gt;You can stash your content like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status

Changes not staged &lt;span class="k"&gt;for &lt;/span&gt;commit:
    modified:   README.md
    modified:   mix.exs
    modified:   &lt;span class="nb"&gt;test&lt;/span&gt;/inspyre_web/live/story_live_test.exs

no changes added to commit &lt;span class="o"&gt;(&lt;/span&gt;use &lt;span class="s2"&gt;"git add"&lt;/span&gt; and/or &lt;span class="s2"&gt;"git commit -a"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

git stash

git status

On branch main
Your branch is up to &lt;span class="nb"&gt;date &lt;/span&gt;with &lt;span class="s1"&gt;'origin/main'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like magic your changes are seemingly gone.. or are they?&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;git stash list&lt;/code&gt; you'll see a log of previously stashed events alongside the branch you were operating on and the last commit in that log. &lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;git stash apply&lt;/code&gt; will take the last stashed set of changes and apply them to your current branch &lt;strong&gt;but will not remove them from your stash list&lt;/strong&gt;. If you know you won't need them this one time stash you'll want to use &lt;code&gt;git stash pop&lt;/code&gt; to apply the changes and pop them out of your stash list.&lt;/p&gt;

&lt;h2&gt;
  
  
  git reset --soft HEAD^N
&lt;/h2&gt;

&lt;p&gt;Have you ever accidentally thought you changed branch but really you were still in the last feature you were working on?&lt;/p&gt;

&lt;p&gt;Have you committed multiple times?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whoops&lt;/strong&gt;. It's cool - we can fix that. &lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;git reset --soft HEAD^N&lt;/code&gt; where N is the number of commits you want to un-commit to bring them back to you. From here you can stash or move to another branch and commit them there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be careful not to type &lt;code&gt;--hard&lt;/code&gt; though. That'll trash unsaved changes for good.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  git reflog
&lt;/h2&gt;

&lt;p&gt;Gits secret weapon / time capsule. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;git reflog&lt;/code&gt; will give you a list of every single thing you've done in git across every single branch. &lt;/p&gt;

&lt;p&gt;If you've accidentally ended up in a state you weren't expecting to be in, deleted things, merged things accidentally or can't figure out what's happened, reach for &lt;code&gt;git reflog&lt;/code&gt; (at least before you trash everything and re-clone your repo).&lt;/p&gt;

&lt;h2&gt;
  
  
  git branch -M (BONUS)
&lt;/h2&gt;

&lt;p&gt;This one is simple but effective - and one I know several devs resort to deleting and recreating a branch to solve!  🤯 &lt;/p&gt;

&lt;p&gt;Renaming a branch!&lt;/p&gt;

&lt;p&gt;Simply type &lt;code&gt;git branch -M &amp;lt;new_branch_name&amp;gt;&lt;/code&gt; to set your new branch name for the branch your currently in.&lt;/p&gt;

&lt;p&gt;That's all folks. &lt;/p&gt;

&lt;p&gt;Hopefully that was useful for some - subscribe to my &lt;a href="https://chrisgregori.substack.com/"&gt;Substack&lt;/a&gt; for similar content and &lt;a href="https://twitter.com/codestirring"&gt;follow me on Twitter&lt;/a&gt; for more git (and general programming) tips.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>git</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why do developers experience so much imposter syndrome?</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Thu, 30 Jun 2022 09:33:27 +0000</pubDate>
      <link>https://dev.to/chriis/why-do-developers-experience-so-much-imposter-syndrome-92g</link>
      <guid>https://dev.to/chriis/why-do-developers-experience-so-much-imposter-syndrome-92g</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The persistent inability to believe that one's success is deserved or has been legitimately achieved as a result of one's own efforts or skills. - Oxford Dictionary&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Essentially a psychological occurrence in which someone (in the case of this article, a developer) doubts their skills, talents or accomplishments despite clear external evidence suggesting otherwise.&lt;/p&gt;

&lt;p&gt;Almost every developer - irrespective of education or experience - has felt it at some stage of their career - and if they say they haven't, &lt;em&gt;I don't believe them.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is it so prevalent in software?
&lt;/h2&gt;

&lt;p&gt;It's due to the very soul of the tech industry - a symptom of the open, free sharing, nature of the job. With so many different tech stacks, languages, paradigms, layers of logic and knowledge, it's literally impossible for a developer to know absolutely everything.&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;will&lt;/em&gt; come across someone that knows more about a topic than you do. &lt;/p&gt;

&lt;p&gt;Is it a language feature that'll set you off? A design pattern? Knowing how to host and distribute software? AI? Blockchain? Web3? SEO? Accessibility? Web design? Performance? Systems design? UX? &lt;/p&gt;

&lt;p&gt;We expose ourselves to as much as we can to make ourselves better in our roles - hell, the job itself is about constant learning to solve problems. &lt;strong&gt;Our job is about learning things.&lt;/strong&gt; If a new ticket emerges tomorrow on your board and you don't know how to solve it, you're supposed to go and figure out how to do it. That's the job.&lt;/p&gt;

&lt;p&gt;The modern web developer browses the internet daily for assistance, news and updates about their job - this culminates in more exposure to more things we don't know, and that can be a scary, scary thing for someone unsure of themselves in a professional capacity. Read something on Twitter? An article on Hackernews or Medium? Did someone just announce a new library on Reddit about something you feel like you &lt;em&gt;should&lt;/em&gt; know about?&lt;/p&gt;

&lt;p&gt;Chances are, that can be the trigger for that anxiety and ultimately make you feel like an imposter, and that's before even considering how quickly things change around here. &lt;/p&gt;

&lt;p&gt;The rate that this industry moves is absolutely staggering. There is &lt;em&gt;always&lt;/em&gt; going to be more to learn and it'll come at you at a pace that most humans can't keep up with. My team built a state-of-the-art marketing website with all the bells and whistles one could hope for around a year ago using some of the most bleeding edge, production ready tech available. Today, spending six hours on Twitter and Hackernews will tell you that your tech stack is archaic and that you should be building everything in &lt;a href="https://deno.com/deploy"&gt;Deno&lt;/a&gt; and &lt;a href="https://deno.com/blog/fresh-is-stable"&gt;Fresh&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  So, what is the cure?
&lt;/h2&gt;

&lt;p&gt;Honestly, it never really goes away. &lt;strong&gt;Sorry, but that's the truth&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At the time of writing this, I'll have been working as a professional Software Engineer for over 9 years.&lt;/p&gt;

&lt;p&gt;I have worked with engineers to create software that has won accolades, won hackathons against a plethora of talented engineers, been promoted several times across multiple organisations and now lead a team due to my &lt;em&gt;supposed&lt;/em&gt; knowledge. &lt;strong&gt;But it doesn't matter&lt;/strong&gt; - every now and then (&lt;em&gt;read: weekly&lt;/em&gt;) I'll see something online or talk to someone and feel like I'm a fraud. It happens. I know this is the case for other engineers I've spoken to as well, but even if there's no cure, there &lt;em&gt;is&lt;/em&gt; medicine to relieve the symptoms. &lt;/p&gt;



&lt;h3&gt;
  
  
  Embrace the opportunity
&lt;/h3&gt;

&lt;p&gt;Re-frame your mindset. If you come across a person or an experience that triggers that feeling of not knowing, take the bull by the horns; ask questions, admit that you don't know something and take it as an opportunity to learn and get better. It's better to be humble and admit you don't know something if it presents a chance to fix it.&lt;/p&gt;

&lt;p&gt;Do you find that there's an insurmountable number of things that you need to learn? &lt;em&gt;Prioritise&lt;/em&gt;. Write them all down, score them according to their importance, or how much they interest you or perhaps which topic would be most relevant. &lt;/p&gt;

&lt;p&gt;Life is about learning - embrace the opportunity to learn something today that you didn't know yesterday.&lt;/p&gt;

&lt;h3&gt;
  
  
  Embrace what that desire to learn really means
&lt;/h3&gt;

&lt;p&gt;If not knowing something is upsetting you, it's likely that it's because you care and you want to improve. If you have the capacity and desire to be honest about what you know and don't, are able to learn new skills, tech stacks and paradigms then that's as much of a definition of the job as there'll ever be.&lt;/p&gt;

&lt;p&gt;Recognise that and recognise that it's a better situation to be in than thinking you know everything. You don't. No one does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rationalise the facts
&lt;/h3&gt;

&lt;p&gt;Start listing the facts. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Out of the following scenarios, which is more likely?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;That you scammed your way through all of your credentials, tricked every experienced interviewer you met and bamboozled a company into paying you a good salary to do a job you're not equipped to do&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You know how to do your job, you've proved that through a series of rigorous tests which &lt;em&gt;are researched and designed by "the professional developers" to weed out candidates&lt;/em&gt;, and met the criteria of a company willing to pay someone an agreed upon wage to do a job they believe you can do&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Be really honest with yourself here. &lt;/p&gt;

&lt;h3&gt;
  
  
  Encourage your peers and promote collaboration
&lt;/h3&gt;

&lt;p&gt;Software development is a team sport - almost every single product worth its merit - be that a website, an open source library you use, the circuit powering the device you're reading this on - has been built by a team of people with different skills all working together.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encourage teamwork &lt;/li&gt;
&lt;li&gt;Recognise failure as an opportunity to learn and celebrate wins together &lt;/li&gt;
&lt;li&gt;Pair program &lt;/li&gt;
&lt;li&gt;Mob program &lt;/li&gt;
&lt;li&gt;Write the code together&lt;/li&gt;
&lt;li&gt;Write the systems design document in a group&lt;/li&gt;
&lt;li&gt;Collaborate&lt;/li&gt;
&lt;li&gt;Teach each other&lt;/li&gt;
&lt;li&gt;Tackle open source issues&lt;/li&gt;
&lt;li&gt;Inspire and challenge each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll be a better developer for it and you'll learn &lt;em&gt;so&lt;/em&gt; much more.&lt;/p&gt;



&lt;p&gt;Ultimately, just remember that there will always be a higher bar to compare yourself against - the breadth of possible topics of expertise in this industry makes people feel like they're not up to scratch if they come across something they don't know and that's completely natural.&lt;/p&gt;

&lt;p&gt;Jimi Hendrix couldn't play the guitar until he could.&lt;/p&gt;

&lt;p&gt;Everyone is a beginner until they're not. &lt;/p&gt;

&lt;p&gt;Be okay with the fact that you might come across something you know nothing about, but take solace in the fact that you have the capacity to; you've proven that before.&lt;/p&gt;

</description>
      <category>impostersyndome</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Embracing your own platform for blogging</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Tue, 28 Jun 2022 09:00:22 +0000</pubDate>
      <link>https://dev.to/chriis/embracing-your-own-platform-for-blogging-325j</link>
      <guid>https://dev.to/chriis/embracing-your-own-platform-for-blogging-325j</guid>
      <description>&lt;h2&gt;
  
  
  👋🏼
&lt;/h2&gt;

&lt;p&gt;My name's Chris Gregori - I'm a full stack software engineer specialising in Elixir and React, currently leading a team at &lt;a href="https://www.multiverse.io"&gt;Multiverse&lt;/a&gt; - the UK's first &lt;a href="https://www.uktech.news/education/euan-blair-multiverse-edtech-unicorn-20220609"&gt;EdTech unicorn&lt;/a&gt;! (&lt;em&gt;Yes, we're hiring, reach out if you're interested in changing education for the better&lt;/em&gt;). &lt;/p&gt;



&lt;p&gt;This is my new personal site - it's been coming for a while, I initially created it as a Next.js project about a year ago and life (and design fatigue and side project-itis) got in the way until about a week ago when I had a spurt of inspiration. So I scraped 90% of the repository (aside from some static data I had written which was still relevant), upgraded Next to v12.0 and hooked everything up to a new &lt;a href="https://www.sanity.io/"&gt;Sanity.io&lt;/a&gt; project. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Next.js?
&lt;/h2&gt;

&lt;p&gt;Next is a React.js framework. According to the &lt;a href="https://survey.stackoverflow.co/2022/#most-popular-technologies-webframe"&gt;latest Stack Overflow survey&lt;/a&gt; it's getting fairly popular - I'm a huge fan personally. It comes out the box with hybrid client, server, and static rendering, route pre-fetching, an image component that does all the hardwork for you, TypeScript support and more out of the box. &lt;/p&gt;

&lt;p&gt;With static rendering, it means I can pre-fetch all my content at compile time and render it in the lightest way possible to my readers, so it's as fast as can be. Oh, and I'm hosting it on Vercels edge network (for free!) for world wide distribution. &lt;/p&gt;

&lt;p&gt;Personally I think it's the nicest way to get a React project going these days - I'll mention that while I used to specialise in front-end tech, I've been less involved in it recently so feel free to correct me! Remix was also a consideration but I stuck to the devil I knew this time around. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why / What is Sanity?
&lt;/h2&gt;

&lt;p&gt;Sanity is a CMS (content management system) that puts developers first. If you've ever used or integrated with one before you'll likely find that the structure of the content you have to integrate with is strict and uncomfortable and the flexibility is usually limited. Another issue is it's usually all defined in some external service with no source control or ability to enforce rules and validations as and when you need them. &lt;/p&gt;

&lt;p&gt;Sanity does away with that by letting you define all of your objects (think chunks of content) and documents (defined groups of content) in JSON which you control and manage the code for. This means you can create usable pieces, import them into your version of the Sanity editor (Sanity Studio) and deploy it! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's nuts&lt;/strong&gt; - in the new world:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All of your schema can live in source control&lt;/li&gt;
&lt;li&gt;It can be as granular as you like with validation, rules and documentation you surface to your users&lt;/li&gt;
&lt;li&gt;You can create and use community made, open source plugins in your editor&lt;/li&gt;
&lt;li&gt;You can self host it&lt;/li&gt;
&lt;li&gt;It's free&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;I had used Sanity in the last year when we built the Multiverse marketing site (which &lt;a href="https://winners.webbyawards.com/2022/websites-and-mobile-sites/general-websites-and-mobile-sites/employment/212761/multiverse--building-an-effective-marketing-site-and-scaling-the-brand-to-a-new-region-and"&gt;we won a Webby award&lt;/a&gt; for!) from scratch using it with React and Next.js - the development experience was ridiculously nice so I wanted to encorporate some of that into my blogging and personal site. &lt;/p&gt;

&lt;p&gt;My previous personal sites had always been more of a manual affair. I had to do something around the realms of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone or update the repo depending on where I was accessing it from&lt;/li&gt;
&lt;li&gt;Re-teach myself how I'd stored the data&lt;/li&gt;
&lt;li&gt;Write some JS or HTML&lt;/li&gt;
&lt;li&gt;Commit the code&lt;/li&gt;
&lt;li&gt;Push the code to source control&lt;/li&gt;
&lt;li&gt;Re-deploy it manually or FTP it (&lt;em&gt;yes, that's right&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now with Next.js, Vercel hosting and Sanity, it looks more like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access my authorised, hosted Sanity Studio (for free)&lt;/li&gt;
&lt;li&gt;Change whatever I like in Markdown or alter dedicated fields (with validation!)&lt;/li&gt;
&lt;li&gt;Hit publish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've setup webhooks so that everytime I publish from Sanity I trigger a new deployment in Vercel which statically generates all of my content, styling and markup at compile time and hosts it on Vercels edge network globally which means my platform is as performant as can be. Sanity and Next.js also take care of rendering images beautifully with webp, and blured placeholders. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why not blog on a dedicated platform?
&lt;/h2&gt;

&lt;p&gt;I used to love Medium - it's awesome for a bunch of reasons. The design is beautiful, it's given writers a way to grow an audience without having to do the leg work of a self-hosted blog, it's promoted content is normally quite good, the list goes on. &lt;/p&gt;

&lt;p&gt;But over the last few years I'd found myself becoming less and less enamoured with the platform. The introduction of the partner program seems to have bred a culture of writers creating un-original content with spammy titles just to get clicks, it's been YouTube-ified, and that's a real shame.&lt;/p&gt;

&lt;p&gt;There's also the controversy that arose when &lt;a href="https://dev.to/ben/i-m-concerned-with-the-move-that-freecodecamp-just-pulled-by-leaving-medium-io8"&gt;FreeCodeCamp stole everyones content without consent&lt;/a&gt;. &lt;strong&gt;Yikes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've also found that I sometimes wanted more powerful editing features. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seriously Medium, it's 2022, why do I still have to host code snippets in gists and embed them?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That said, I still like the platform and I'll be cross-posting there too for increased exposure thanks to the power of cannonical URLs. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's new and funky?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MDX
&lt;/h3&gt;

&lt;p&gt;This is one of my favourite bits - I'm using MDX for my blog posts which means I can write my content in markdown in Sanity and include JSX in the content itself which gets parsed and rendered out to the user. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sparkly content omitted because it's not the original post&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Since I can render React components (that my code knows about beforehand) I can do some pretty powerful stuff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code editor omitted because it's not the original post&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Snippets with Prism
&lt;/h3&gt;

&lt;p&gt;I've also added code snippets as you'd expect from any decent developer blog. This snippet is how I determine if I should add a sparkly "New" tag next to my blog post listings on the homepage.&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;NewTag&lt;/span&gt; &lt;span class="o"&gt;=&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="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;oneWeekAgo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;subtract&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="s1"&gt;week&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;publishedDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dayjs&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isNew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;publishedDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAfter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oneWeekAgo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;week&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;isNew&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Sparkles&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;New&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Tag&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;Sparkles&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lottie
&lt;/h3&gt;

&lt;p&gt;If you scroll to the end of the original blog post (hopefully after reading all of this delightful content), you'll see a lottie animation fire off. How cool. &lt;/p&gt;

&lt;p&gt;The keen-eyed amongst you reading on desktop might have also noticed a progress indicator in the top left of the screen signaling how far you are through the post itself. This, and the lottie trigger are tracked using a &lt;code&gt;useEffect&lt;/code&gt; hook alongside some magic from &lt;code&gt;framer-motion&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;scrollYProgress&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useViewportScroll&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;yRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTransform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scrollYProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pathLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSpring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yRange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;stiffness&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;damping&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;90&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;lottieRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;yRange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;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="nx"&gt;setTimeout&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;lottieRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;500&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="nx"&gt;yRange&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cool, what's going to be on here?
&lt;/h2&gt;

&lt;p&gt;I'm going to be blogging a lot more this year I hope and on a vast range of topics, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elixir, Phoenix and LiveView &lt;/li&gt;
&lt;li&gt;Front-end technologies like React, Svelte and Vue&lt;/li&gt;
&lt;li&gt;CSS tips &lt;/li&gt;
&lt;li&gt;New language deep dives&lt;/li&gt;
&lt;li&gt;Architecture and macro-design&lt;/li&gt;
&lt;li&gt;My opinions on the technical landscape&lt;/li&gt;
&lt;li&gt;Coding tutorials and code snippets&lt;/li&gt;
&lt;li&gt;Lots, lots more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also do a fair bit of photography if that interests you. &lt;/p&gt;

&lt;h2&gt;
  
  
  How do I keep up?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Lots of ways.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow me on &lt;a href="https://twitter.com/_ChrisGreg"&gt;Twitter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow me on &lt;a href="https://www.instagram.com/chrisgregori__/"&gt;Instagram if you're interested in my photography&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow me on &lt;a href="https://medium.com/@chrisgregori"&gt;Medium&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sign up to my &lt;a href="https://chrisgregori.substack.com/"&gt;SubStack&lt;/a&gt; using the subscription box below to get my articles straight into your inbox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm always down for a chat so feel free to reach out!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>showdev</category>
      <category>portfolio</category>
    </item>
    <item>
      <title>What's new in Node?</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Thu, 30 May 2019 14:00:34 +0000</pubDate>
      <link>https://dev.to/chriis/what-s-new-in-node-4dna</link>
      <guid>https://dev.to/chriis/what-s-new-in-node-4dna</guid>
      <description>&lt;p&gt;I used to solely write Node, React and JavaScript but in the last 1.5y I've been focussed on React-Native, Elm and Elixir.&lt;/p&gt;

&lt;p&gt;I wanna spruce up and get back into it but I fear I may be slightly behind the ecosystem.&lt;/p&gt;

&lt;p&gt;Any massive new libraries, features, patterns, do's/don'ts I should be aware of if I were to start looking for Node jobs anytime soon?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>TIL — Git supports a global exclude file</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Sun, 07 Apr 2019 10:59:08 +0000</pubDate>
      <link>https://dev.to/chriis/til-git-supports-a-global-exclude-file-11ko</link>
      <guid>https://dev.to/chriis/til-git-supports-a-global-exclude-file-11ko</guid>
      <description>&lt;h3&gt;
  
  
  TIL — Git supports a global exclude file
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A tiny tip that might help a lot of you
&lt;/h4&gt;

&lt;p&gt;I don’t really know why I didn’t think this was a thing until today but I was having some issues with elixir_ls (a VSCode plugin for Elixir development) plaguing my git repository up and my projects .gitignore file was seemingly ignoring the generated files.&lt;/p&gt;

&lt;p&gt;There also seem to be some Github issues talking about the same thing so I wasn’t alone in my folly.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aox_aj7StrVzI74o__XeiCA.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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aox_aj7StrVzI74o__XeiCA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;Your git installation can have a global .gitignore file! I’ve been programming for 5 years and had no idea — I’m not really sure why I didn’t consider it in the past.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;To add a global **&lt;/strong&gt;.gitignore file:**
&lt;/h4&gt;

&lt;p&gt;git config --global core.excludesfile ~/.gitignore&lt;/p&gt;

&lt;h4&gt;
  
  
  To edit a global .gitignore file:
&lt;/h4&gt;

&lt;p&gt;sudo vim ~/.gitignore (or an editor of your choice)&lt;/p&gt;

&lt;p&gt;Here are the contents of mine — I took the liberty of adding some other common files I want to ignore in there too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.DS\_Store
node\_modules/
.elixir\_ls/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optional extra
&lt;/h3&gt;

&lt;p&gt;Some of you might do this then find that your .gitignore hasn’t taken effect — the following commands will fix this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add [uncommitted changes you want to keep] &amp;amp;&amp;amp; git commit
git rm -r --cached .
git add .
git commit -m "fixed untracked files"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope this helped! It cleared up my VScode woes.&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AVNNeZVL_anR3JxQYZeDfoQ.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AVNNeZVL_anR3JxQYZeDfoQ.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoyed my ramblings? Follow me on&lt;/em&gt; &lt;a href="https://twitter.com/_ChrisGreg" rel="noopener noreferrer"&gt;&lt;em&gt;twitter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to hear more of my development tales or keep up with my side projects on my&lt;/em&gt; &lt;a href="http://chrisgregori.co.uk/" rel="noopener noreferrer"&gt;&lt;em&gt;personal site&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. 💻&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gitflow</category>
      <category>git</category>
      <category>elixir</category>
      <category>elixirlang</category>
    </item>
    <item>
      <title>“Why should I leave?”</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Tue, 05 Mar 2019 17:22:24 +0000</pubDate>
      <link>https://dev.to/chriis/why-should-i-leave-16ea</link>
      <guid>https://dev.to/chriis/why-should-i-leave-16ea</guid>
      <description>

&lt;p&gt;An open insight into what it’s like to leave a comfy Software Engineering job and venture into the unknown.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There’s a TL;DR… at the bottom.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pwrXvH52--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A74z7jfNCr_zDldtRRaa-zw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pwrXvH52--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A74z7jfNCr_zDldtRRaa-zw.jpeg" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/oUPywYZT88Y?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Andrew DesLauriers&lt;/a&gt; on &lt;a href="https://unsplash.com/collections/1846973/searching?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over the last 3 years I’ve worked at 3 different companies; in this post I’m going to outline the real benefits and losses I’ve experienced by moving away from one of the best jobs I’ve ever had.&lt;/p&gt;

&lt;p&gt;This is a personal account of my time and experience at these companies and it should in no way muddy your opinion of the companies themselves or the people that work there, this is just a recollection of my experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Engineering Timeline
&lt;/h3&gt;

&lt;p&gt;Thomson Reuters : &lt;strong&gt;2012 (Not covered / University industry placement)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Net-A-Porter Graduate Scheme : &lt;strong&gt;2014–2018&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
SkyScanner : &lt;strong&gt;2018–2019&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
WhiteHat GB : &lt;strong&gt;2019-Present&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Net-A-Porter
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Background
&lt;/h4&gt;

&lt;p&gt;I joined NET-A-Porter (will be subsequently referred to as &lt;strong&gt;YNAP&lt;/strong&gt; ) in 2014 as a graduate. Over the course of 4 fantastic years I established myself as a Software Engineer thanks to the tutelage of the incredible people and mentors I had there, and due to the different paradigms, logic/business problems, and experiences I was lucky enough to be exposed to there.&lt;/p&gt;

&lt;p&gt;I loved my job, genuinely. I would wake up and look forward to going in — something I know many people aren’t fortunate enough to experience in their careers — but the reasons for my adoration for my workplace started to dwindle and I had my career prospects to think about. The issue is that I had grown to adore the people and the comfort, and I was genuinely scared that I wouldn’t survive at other jobs for a variety of reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I don’t have the skills for another job (imposter syndrome at it’s finest)&lt;/li&gt;
&lt;li&gt;I wouldn’t manage to form meaningful bonds with other colleagues like I had done at this one&lt;/li&gt;
&lt;li&gt;Other jobs would expect far more from me, NAP was quite comfy&lt;/li&gt;
&lt;li&gt;“I’d miss the people too much”&lt;/li&gt;
&lt;li&gt;What if the technology isn’t as cutting edge? NAP was happy to test out bleeding edge if it made sense&lt;/li&gt;
&lt;li&gt;I really don’t have the skills for another job (again)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The company was a great kick off point for my career; I managed to hop different stacks and teams as a graduate (Java, Scala, Node, React, Vue, Swift, Perl, Ruby), and eventually settled into a Node/React role in one of the most important teams in the company. I was able to make a real impact over the next few years working on plenty of large scale projects.&lt;/p&gt;

&lt;p&gt;Aside from the great technical challenges I was faced with I also managed to experience what it’s like to work at a company that really does have a great culture; colleagues were actually friends with each other, after/during/before work social gatherings were the norm; everyone was great, I loved the people there. This is largely due to the heavy emphasis that was put on during the hiring stages to ensure that the people joining valued the same things as the company.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fun fact:&lt;/strong&gt; did you know that statistically, the companies with the worst working cultures are the ones that brag about it as a selling point? It’s because employees start with very high expectations of what to expect, most of which are never met&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Hints of danger
&lt;/h4&gt;

&lt;p&gt;The good times lasted for some years until things started to change shape. After some large scale business and technical direction changes, my day to day work wasn’t as profound as I once found it to be — I won’t go into specifics here but I stopped being interested in the type of work that was coming my way and the type of work I foresaw the company (and subsequently myself) doing. People started to see this shift and began leaving, this shouldn’t be shocking to anyone and it can’t always be attributed to company issues, some people just want a change of scenery after a few years.&lt;/p&gt;

&lt;p&gt;Alongside all of this I had been tinkering around in exciting, different languages and stacks in my own time and found myself really wanting to work in a more backend focussed role, specifically I fell for Golang— slight issue here is that a lot of my professional experience at this point wasn’t geared towards a backend role without a significant dip in salary; I had some but I lacked database experience and other traditional tricks of the trade. Call it greed but I wanted to become a different type of engineer without slashing my income dramatically.&lt;/p&gt;

&lt;h4&gt;
  
  
  Moving on
&lt;/h4&gt;

&lt;p&gt;So I started looking for another job in September 2017. Luckily YNAP put me in a good position CV wise thanks to some of the incredible work some of my colleagues were becoming known for in the tech world and I received an influx of interview offers from plenty of different companies; this is my imposter syndrome talking too, in actuality I had done some good work, won some hackdays, created some fairly successful side projects, was pretty well trained and had been told I was a good developer. I turned down a few offers when I realised they weren’t offering what I wanted (or thought I wanted?) tech/product wise. I was also scared, I kept making excuses for the companies that were offering me roles or interviews and kept putting it off for a few months.&lt;/p&gt;

&lt;p&gt;In April 2018, I finally summoned the courage to leave after a few melting points at work and landed a job as a Full-Stack Developer at SkyScanner which seemed to fit the bill.&lt;/p&gt;

&lt;p&gt;It didn’t in the end, but that’s okay.&lt;/p&gt;

&lt;h3&gt;
  
  
  SkyScanner
&lt;/h3&gt;

&lt;p&gt;I joined and immediately began working in a small, autonomous team that was focussed on re-creating a part of the mobile applications in React-Native. The team was highly motivated, had some good knowledge of the domains and stack we’d be working on and the project seemed quite cool.&lt;/p&gt;

&lt;p&gt;So how was I doing?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New technology requirement ✅&lt;/li&gt;
&lt;li&gt;Substantial salary bump ✅&lt;/li&gt;
&lt;li&gt;Good team ✅&lt;/li&gt;
&lt;li&gt;Backend work? ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pretty good right? Kind of.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/cff7d4a5b868c807c4740d95e5466903/href"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/cff7d4a5b868c807c4740d95e5466903/href"&gt;https://medium.com/media/cff7d4a5b868c807c4740d95e5466903/href&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You see what SkyScanner offered me the position they weren’t clear about what tech stack I’d be doing and stressed that I’d be put into an appropriate team that matched my skillset upon accepting. I let them know that I really did not want to work on Java simply because I hated working with it and that I didn’t want to be stuck in front-end again; they seemed on board and their other tech stacks seemed appropriate.&lt;/p&gt;

&lt;h4&gt;
  
  
  Initial thoughts
&lt;/h4&gt;

&lt;p&gt;When I first got there, the team (newly formed from new hires without strict JS backgrounds) was finishing off an MVP of a React Native prototype they had built to see if the stack stood up to the project requirements. It made sense, required less engineers for a multi-platform native application, the project didn’t require any niche platform functionality that RN couldn’t provide and we could still make it look good. After a few months of learning React-Native (very small learning curve if you’ve done React on web) and creating the new version of the app it turned out that the team needed a backend system to proxy and aggregate the calls we were making for our app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cool, finally I can work on some backend stuff, and get the experience I so desperately desired.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well the team wanted to build it in Java due to their backgrounds. Much to my dismay, it made sense, it fit the purpose and Java had a strong backing from the company so tools and help were readily available. Okay fair enough, I could get on board despite me trying to get stacks like Golang or Elixir or &lt;strong&gt;&amp;lt;Insert CVDD tech stack here&amp;gt;&lt;/strong&gt; in the picture.&lt;/p&gt;

&lt;p&gt;Excited to finally get going on some backend work, I found out that the company had a “Developer Enablement” team. Their job was to create scripts and tooling around developer experience and cookie cutter builds. It was extremely useful and very productive to have a secure, logging-ready, CI/CD, AWS dev/prod and terraformed application ready simply by running a CLI command.&lt;/p&gt;

&lt;p&gt;As productive as that was I was disappointed that I couldn’t learn anything about the process of setting any of that up because it had already been done for me at the push of a button, no ops knowledge or Java skills to pick up there at all. In my opinion a large amount of knowledge comes from setting up systems from scratch, you learn how things are coupled, where things live and how things interact.&lt;/p&gt;

&lt;p&gt;The actual work there was to do on the Java side wasn’t exactly what I wanted either — I wanted to work on distributed systems, build microservices working at scale, optimising DB queries, analysing streams of data etc. The app was simple and proxied requests to a few internal systems and told the app how to behave — nothing I hadn’t already done before in other stacks. Ignoring this the team was composed of engineers from a variety of backgrounds and guess what, Software Engineers are opinionated, if some of them only wants to work in Java they’ll probably only pick up the Java tickets, so guess who was charged with doing most of the React work alongside developers that wanted to write JavaScript like enterprise Java?&lt;/p&gt;

&lt;p&gt;You guessed it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/408db45ebdb83f608e78dd68af3fcf17/href"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/408db45ebdb83f608e78dd68af3fcf17/href"&gt;https://medium.com/media/408db45ebdb83f608e78dd68af3fcf17/href&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright so I wasn’t happy with the tech, what about the product I was building itself? Well after 6 or so months we released a version of the application we planned out after we pivoted a few times due to some decisions from the higher ups. The app wasn’t bad and we were releasing updates frequently in an agile fashion — but I was still stuck in a position of working on React Native (read: React), all the while I felt like my skills were dwindling in other areas — I was no longer configuring webpack (a blessing really), I wasn’t doing any web performance tweaking, I wasn’t doing any Node or backend work and I’d lost my opportunity to touch AWS. Mobile was also a far more restrictive and annoying platform to release to in my opinion. Overall, I felt like I was stagnating as a developer.&lt;/p&gt;

&lt;p&gt;Along with this issues I had also realised that many of the other developers on my team weren’t really that engaged — whilst that shouldn’t effect me, it’s hard to get invested in a team and a product when your colleagues are pointing out (very valid) flaws day-in-day-out.&lt;/p&gt;

&lt;h4&gt;
  
  
  So what did this job give me?
&lt;/h4&gt;

&lt;p&gt;Confidence and clarity (and a pay raise).&lt;/p&gt;

&lt;p&gt;The React Native skills were nice and I still use them to create small apps on the side in my own time. But the most valuable thing I took from this position is the knowledge that changing jobs doesn’t have to be scary. I made it through with more clarity and some tangible CV skills, and a bump in pay.&lt;/p&gt;

&lt;p&gt;Was it perfect? No, but it was a learning experience.&lt;/p&gt;

&lt;p&gt;Did I make intense meaningful connections to people? Not really, I made friends, some of whom I still keep in touch with, but I shouldn’t have ever expected that I’d form the same bonds with the people that I began my career with over 4 years in every work place. It would’ve been a great bonus but it wasn’t necessary — I still keep in touch with the people that matter and friends come from all avenues of life.&lt;/p&gt;

&lt;p&gt;I only left after 10 months but that was my decision because I had realised what I wanted from a job and what I didn’t. I needed a role that would at least let me explore backend development and work with databases. I needed something different to keep my interest. I needed a product that I actually cared about building.&lt;/p&gt;

&lt;p&gt;After a month or so of looking for new work (and a brief idea of contracting) I found a lovely start-up that’s looking to really help people and empower a new generation of world leaders in WhiteHat.&lt;/p&gt;

&lt;h3&gt;
  
  
  WhiteHat
&lt;/h3&gt;

&lt;p&gt;As of writing this I’ve only been at WhiteHat for 1.5 months, it’s a challenging environment and I’m having to learn faster and more effectively due to the startup nature, and due to the fact that the entire tech stack is built in Elixir, Elm and PostgresDB, and aside from what I’ve gathered from ES6 and Redux, I’ve never done any functional programming.&lt;/p&gt;

&lt;p&gt;But I’m learning, I’m meeting people, I’m seeing engineering life through the eyes of a small company that’s rapidly growing and expanding it’s territory and I’m excited. The future is bright for this little ~50 person start-up and I think we can do great things.&lt;/p&gt;

&lt;p&gt;Aside from being pumped to get into a whole new tech stack and get some experience doing backend work, I’m actually optimistic about what we can achieve and what we’re doing, it’s a mission that isn’t just selling expensive things to people that can afford it, and it turns out that’s important to me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Take aways
&lt;/h3&gt;

&lt;p&gt;Moving jobs is scary. Especially if you’ve been there for a while and resonate with the people and the memories you’ve had there. But if you’re finding yourself no longer challenged, no longer interested, no longer learning or no longer caring about the work that you’re doing then maybe it’s time to look elsewhere.&lt;/p&gt;

&lt;p&gt;It doesn’t have to be as scary as you think.&lt;/p&gt;

&lt;p&gt;Other companies are also doing incredible things. Just because your current company does some things in a great way doesn’t mean others don’t and it doesn’t mean you’d be missing out elsewhere.&lt;/p&gt;

&lt;p&gt;SkyScanner had an incredible devops setup which really blew me away. It also had some immensely talented people working in lots of different, varied teams and it was trying to establish an objectively good working culture — even if I had some issues with it.&lt;/p&gt;

&lt;p&gt;Net-A-Porter had an immensely sharp eye for detail in it’s front-end technical teams and were headed up by some fantastic product, tech and delivery leads. My old teams admiration and drive to get testing, performance and user experience nailed was immense and it helped mould me into the developer I am today. It was also home to some of the most incredible people I know.&lt;/p&gt;

&lt;p&gt;But you learn things by moving and it helps you get over the fear. I’m not scared of looking for new opportunities as I once was because I now know that whilst the grass isn’t always greener, it’ll still give you learning experiences and teach you things about the industry and yourself that you didn’t know.&lt;/p&gt;

&lt;h4&gt;
  
  
  Your turn
&lt;/h4&gt;

&lt;p&gt;If you know exactly what you want to be working on, what excites you and you’ve gathered or are working on the skills needed for it then you’re half way there.&lt;/p&gt;

&lt;p&gt;Software Engineers are lucky — the market is currently fantastic and innovations in tech are bringing about new opportunities every day. Just make sure that when you’re looking for them you really question what’s important to you.&lt;/p&gt;

&lt;p&gt;In interviews, ask about the culture, ask them about what sort of work you’re really going to be doing and see if you can talk to the developers that already work there. Get an insight into how they release, how they build things, what’s in the roadmap, how they get feedback on their product, how they A/B test, how they test in general, really dig deep.&lt;/p&gt;

&lt;p&gt;Also remember that when you’re being interviewed, you’re also interviewing them. Don’t sell yourself short and recognise that this company wants you otherwise they wouldn’t bother taking the time to find out.&lt;/p&gt;

&lt;p&gt;They have needs but so do you.&lt;/p&gt;

&lt;h4&gt;
  
  
  TL;DR
&lt;/h4&gt;

&lt;p&gt;By moving jobs you release yourself of the fear that other jobs won’t be as good or that you won’t make as many friends or have as good of a time. You might not, but each time you move you’ll expose yourself to new ways of thinking, new tech stacks, different work cultures and a bump in salary because let’s be honest, people care about money because money is important. Move and you’ll get more than staying (generally).&lt;/p&gt;

&lt;p&gt;Be picky about where you wanna go and know what it is you want out of the job. Is it the product, the tech, the money? Know what you want, learn the skills and don’t get attached to a place because you are good enough to work elsewhere, even if you don’t believe you are.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/3036ebf1372b812578b622f81b6c5de0/href"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/3036ebf1372b812578b622f81b6c5de0/href"&gt;https://medium.com/media/3036ebf1372b812578b622f81b6c5de0/href&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoyed my ramblings? Follow me on&lt;/em&gt; &lt;a href="https://twitter.com/_ChrisGreg"&gt;&lt;em&gt;twitter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to hear more of my development tales or keep up with my side projects on my&lt;/em&gt; &lt;a href="http://chrisgregori.co.uk/"&gt;&lt;em&gt;personal site&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. 💻&lt;/em&gt;&lt;/p&gt;





</description>
      <category>impostersyndrome</category>
      <category>softwareengineering</category>
      <category>careeradvice</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>My new approach to finding a gap in the app market</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Sun, 13 Jan 2019 19:13:22 +0000</pubDate>
      <link>https://dev.to/chriis/my-new-approach-to-finding-a-gap-in-the-app-market-562c</link>
      <guid>https://dev.to/chriis/my-new-approach-to-finding-a-gap-in-the-app-market-562c</guid>
      <description>

&lt;h4&gt;
  
  
  A different take on making a side project profitable in this saturated app world.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NzOkVCLd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADJHNfNbm5batlJtu-nYK9Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NzOkVCLd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADJHNfNbm5batlJtu-nYK9Q.jpeg" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/rENRXgLsDEQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;rawpixel&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/app?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A problem a lot of developers I know have is thinking about what they can apply their newfound superpowers to: launching a side business or creating apps to make millions (the most common in my experience), developing embedded systems to automate your home, web apps to help manage your at-work pingpong tournaments and more.&lt;/p&gt;

&lt;p&gt;A major issue with the first one is that the market, between both Android and iOS, has over 4 million apps for your potential customers to download — how are your customers supposed discover your new vegan recipe app amongst the clones of Flappy Birds, Bejewelled rip offs and Instagram-story-optimisers?&lt;/p&gt;

&lt;p&gt;Secondly, what makes your idea original enough for people to download it?&lt;/p&gt;

&lt;p&gt;My take is that it doesn’t need to be.&lt;/p&gt;

&lt;p&gt;The app store is plagued by thousands of games, and apps that barely work that’ve been made to fill a gap in the market that was relevant at the time. Years ago someone uploaded the first 3-minute ab workout routine generator because one didn’t exist. That person likely made a small fortune from their app and might be thinking about how lucky they were to be the first to do so. App ideas are now seldom original — yes with the emergence of powerful and exciting new toolkits and technologies like machine learning and AR we will see new innovations in the app space, and some people really can think of incredible, innovative ideas, but maybe you can’t and you’re kicking yourself about the fact that everything with a public and free to use API has already been done.&lt;/p&gt;

&lt;p&gt;So what are you to do? Reinvent the wheel.&lt;/p&gt;

&lt;h4&gt;
  
  
  My Take
&lt;/h4&gt;

&lt;p&gt;I created &lt;strong&gt;Seagull Trainer&lt;/strong&gt; , a £2, fully-fledged, Kegel training app built to be a little bit fairer to the people looking for apps to help reinforce their pelvic floor muscles. A friend of mine told me he started using a &lt;em&gt;free&lt;/em&gt; kegel training app on Android and showed me how the app worked — he was able to get 3 sessions in (which included 2 manoeuvres) before he was told he had to buy the remaining 97 sessions via in-app-purchases for £8 in total. He bought the sessions! I thought this was ridiculous so I decided to make a better looking, gamified version with more features, a well researched routine and answer questions commonly found in the Kegel world by browsing forums and research sites.&lt;/p&gt;

&lt;p&gt;Would making the app free be a more fair thing to do? Yes but my time is also valuable to me and £2 is less than the price of most peoples morning coffees. Also ads suck.&lt;/p&gt;

&lt;p&gt;The app is currently bringing in more money (almost definitely far less than whatever figure you’re imagining) than any of my free + ads apps are. Yes with an obscene amount of volume these freemium apps can make a good amount of money but they’re also usually in the realm of apps that have already been done to death or require an obscene amount of effort to beat the competition — why not go for the tried and tested salesmen approach of undercutting the competition with a better product?&lt;/p&gt;

&lt;p&gt;This also helps get around your first issue (app discovery); hundreds of app ideas have been farmed into this ‘just about works and costs money’ niche and due to the sheer number of users on these app stores, people are biting. If people are searching for these things anyway, put the best option in their eyes and they just might give it a go given enough polish, screenshots, honesty and positive reviews.&lt;/p&gt;

&lt;p&gt;By following this approach, we purge the app store of poorly implemented, money-grabbing apps that appear free then charge obscene amounts for basic functionality — it may also help you get that elusive side hustle started. Consider a solution that improves upon badly implemented, freemium, good ideas next time you’re racking your brain for a side project to work on, especially if you see something niche. And who knows, maybe one day people will finally be okay with spending less than the price of a coffee for a tool that could revolutionise multiple aspects of their life.&lt;/p&gt;

&lt;p&gt;Win, win.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--76A1-cTI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AqSNK5Pl28poeRj42vTgAcw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--76A1-cTI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AqSNK5Pl28poeRj42vTgAcw.jpeg" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/photos/gVWQJQEc6lA?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;rawpixel&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/win?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Wanna give Seagull Trainer a spin? Here’s a link:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://itunes.apple.com/us/app/seagull-trainer-kegel-trainer/id1436715497?mt=8&amp;amp;ref=producthunt"&gt;Seagull Trainer iOS Store&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoyed my ramblings? Follow me on&lt;/em&gt; &lt;a href="https://twitter.com/_ChrisGreg"&gt;&lt;em&gt;twitter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to hear more of my development tales or keep up with my side projects on my&lt;/em&gt; &lt;a href="http://chrisgregori.co.uk/"&gt;&lt;em&gt;personal site&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. 💻&lt;/em&gt;&lt;/p&gt;





</description>
      <category>ios</category>
      <category>appstore</category>
      <category>iosdevelopment</category>
      <category>kegels</category>
    </item>
    <item>
      <title>How my silly app turned into something potentially useful</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Sun, 12 Aug 2018 10:31:01 +0000</pubDate>
      <link>https://dev.to/chriis/how-my-silly-app-turned-into-something-potentially-useful-955</link>
      <guid>https://dev.to/chriis/how-my-silly-app-turned-into-something-potentially-useful-955</guid>
      <description>

&lt;h4&gt;
  
  
  Turns out that logging users poops on a map in real time can actually be something that helps everyone.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uyaSjlJ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A6_XT_6YfFqKBQ_DBZ7UkjA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uyaSjlJ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A6_XT_6YfFqKBQ_DBZ7UkjA.jpeg" alt=""&gt;&lt;/a&gt;Dan Edwards — Unsplash&lt;/p&gt;

&lt;h4&gt;
  
  
  Backstory
&lt;/h4&gt;

&lt;p&gt;Around year ago I began looking into React Native; as a web developer the idea of creating native applications without having to master multiple ecosystems and stacks was incredible. I personally love apps — I know some people prefer web experiences or PWAs to save their devices storage space or don’t want to download something for a one off use but I just find apps tend to have better UI and UX — good enough that I’m happy to download them.&lt;/p&gt;

&lt;p&gt;I don’t want to start a web vs native war here — they’re both great and some web apps are definitely better than their native counterparts; in my experience however, apps are usually more refined.&lt;/p&gt;

&lt;p&gt;Anyway I wanted some sort of project to build that wasn’t just a todo list or a notes app; I wanted something a bit more technically challenging so I could test if React Native could actually be utilised by a company or for a real world application. I was also beginning a job at SkyScanner as a React Native engineer so I wanted some hands on experience before starting the job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RJLjgV6A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADBXOkTARqfU_Szz2_g7AAw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RJLjgV6A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADBXOkTARqfU_Szz2_g7AAw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Implementation
&lt;/h4&gt;

&lt;p&gt;Introducing Logger: The Poop Tracker!&lt;/p&gt;

&lt;p&gt;Logger is an idea stemming from a pun that I won’t explain; the short and sweet of it is that it’s a real-time, GPS tracking, logging application utilising Facebook oAuth and Google Maps. It’s powered by Firebase (which is incredible and free to a point) and it’s completely free.&lt;/p&gt;

&lt;p&gt;A summary is it’s app with a real-time feed logging every users public logs. Each log has a star rating associated (because why not) and each user has a profile page they can use to see their average stars, their day/night ratio and where they use it.&lt;/p&gt;

&lt;p&gt;The actual implementation isn’t anything magical — it logs to Firebase and makes use of Expos fantastic library of features such as a MapView and Facebook oAuth to authenticate, store and show logs on a map.&lt;/p&gt;

&lt;h4&gt;
  
  
  Launch
&lt;/h4&gt;

&lt;p&gt;Logger was built as a joke — it was something my friend started making then he gave up, so I thought why don’t I use this as the base of my React Native training. It took me around 4 months of on and off starting and stopping — mostly due to some libraries not playing nicely (mainly React Navigation) and because it’s hard to stay motivated on a project that’s so silly and has no use.&lt;/p&gt;

&lt;p&gt;The thing is though, Logger does have a use — multiple actually. After I released it I realised that it was actually being used from various spots around the world: USA, parts of Asia, Europe; I didn’t even spend any money or real effort promoting it — word of mouth, humour and the magic of the App Store had taken it into users hands.&lt;/p&gt;

&lt;p&gt;That’s when I realised the crowd sourced information could actually be used for something…&lt;/p&gt;

&lt;h4&gt;
  
  
  Toilets
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;Everybody poops. There’s even a book about it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On the second day of Loggers release to the App Store I added a feature by adding a new map tab, adding a toggle on the log function, and utilising the platform that I had built: “ &lt;strong&gt;Public Toilet?&lt;/strong&gt; ”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H35Pbou4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ArIMnQ_UNTdfSuh2b6T3mvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H35Pbou4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ArIMnQ_UNTdfSuh2b6T3mvg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By adding a way for users to mark if their log was in a public place I was able to map this data and allow all users to see a map of local public toilets available for use. The issue is the information is all crowd sourced — meaning if people don’t use the app, there won’t be toilet information to share — it all begins and ends with the user.&lt;/p&gt;

&lt;p&gt;The mechanisms were all in place, people were already using the app as a joke, but now they had an actual reason to use it. If someone wants to know where the nearest public toilet is or wants to add to the database — they’ve got Logger for that.&lt;/p&gt;

&lt;p&gt;I had used &lt;strong&gt;Expo&lt;/strong&gt; to build and publish my application binary which enabled my favourite part of React Native development — publishing my binary to a CDN. That’s right I didn’t need to release a new app version and go through Apples review process again. Upon hitting Publish my new version was live in seconds — just like a website!&lt;/p&gt;

&lt;h4&gt;
  
  
  Next Steps
&lt;/h4&gt;

&lt;p&gt;Whether I continue developing Logger is based on how many people actually use it — if people find it useful I will continue to support and maintain it. Otherwise this was a fun little experiment to see if I could use my React skills to build a mobile application — and I could!&lt;/p&gt;

&lt;p&gt;React Native is beautiful. It provides a web developer the basis to create and innovate on an entirely different (and at times very scary) native platform without having to immerse themselves in the lands of Swift and Android. If you’ve ever built anything in React before and are confident with how it all fits together — I encourage you to try it, it’s really not that bad.&lt;/p&gt;

&lt;p&gt;That’s not to say I’ve cast native development to the wind — on the contrary React Native still has some short comings; it’s not as nice to animate with as native Swift, it doesn’t always play nicely with some libraries and it produces a fairly large app size if you’re using Expo.&lt;/p&gt;

&lt;p&gt;I’m actually planning on learning Swift (properly this time) to make my second Swift iOS app now that the language is out of infancy. I think I’ll try and make something a little less gross and a little more useful.&lt;/p&gt;

&lt;h4&gt;
  
  
  Download Logger today!
&lt;/h4&gt;

&lt;p&gt;If you’d like to help Logger and spread the public toilet news, please download the app and report back your findings!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://itunes.apple.com/us/app/logger-the-poop-tracker/id1378106600?ls=1&amp;amp;mt=8"&gt;Download for free today by clicking here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perhaps Logger has some other uses I haven’t thought of, let me know in the comments if you can think of anything!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoyed my ramblings? Follow me on&lt;/em&gt; &lt;a href="https://twitter.com/_ChrisGreg"&gt;&lt;em&gt;twitter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to hear more of my development tales or keep up with my side projects on my&lt;/em&gt; &lt;a href="http://chrisgregori.co.uk/"&gt;&lt;em&gt;personal site&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. 💻&lt;/em&gt;&lt;/p&gt;





</description>
      <category>iosappdevelopment</category>
      <category>react</category>
      <category>reactnative</category>
      <category>firebase</category>
    </item>
    <item>
      <title>HTTP Status Codes you probably haven’t heard of</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Wed, 04 Apr 2018 17:53:45 +0000</pubDate>
      <link>https://dev.to/chriis/http-status-codes-you-probably-havent-heard-of-57lk</link>
      <guid>https://dev.to/chriis/http-status-codes-you-probably-havent-heard-of-57lk</guid>
      <description>

&lt;h4&gt;
  
  
  And might not often see in the wild.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P0CM1rla--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AEhz2uGXNdRTqbTrkHb7sNQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P0CM1rla--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AEhz2uGXNdRTqbTrkHb7sNQ.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A colleague of mine stumbled upon a HTTP status code that the team wasn’t sure of: &lt;strong&gt;207&lt;/strong&gt;. When I took a look I stumbled across a few others I hadn’t really been made aware of throughout my 4 year developer career.&lt;/p&gt;

&lt;p&gt;Lets go through some interesting codes…&lt;/p&gt;

&lt;h4&gt;
  
  
  207: Multi-Status
&lt;/h4&gt;

&lt;p&gt;A status code sent to represent information about multiple resources where appropriate.&lt;/p&gt;

&lt;p&gt;Imagine you have an aggregation layer that might make calls against multiple APIs to collate &amp;amp; process the data and return a JSON payload. If one of the calls succeeds and several others fail what’s the API to do?&lt;/p&gt;

&lt;p&gt;It’s not a 4xx, the resource was found; it’s not a 300, there’s no redirect; it’s not a 5xx, the aggregation server didn’t fail to handle something and explode so it’s technically a 200 in the eyes of the app server.&lt;/p&gt;

&lt;p&gt;207 is clever; if implemented properly it’ll give you an XML payload with a description of the information about the success or failure of the layered calls — each element must contain a href to identify the resource. It’s up to the consumer to handle what happens next.&lt;/p&gt;

&lt;h4&gt;
  
  
  411: Length Required
&lt;/h4&gt;

&lt;p&gt;When a server refuses to accept the request without a explicitly defined Content-Length.&lt;/p&gt;

&lt;p&gt;Simple and makes sense but not the most common code you might see.&lt;/p&gt;

&lt;h4&gt;
  
  
  451: Unavailable for Legal Reasons
&lt;/h4&gt;

&lt;p&gt;A status code sent to deny access to a resource as a consequence of a legal demand.&lt;/p&gt;

&lt;p&gt;A 451 response body should include an explanation of the legal demand, the party making it, the applicable legislation or regulation and what classes of person and resource it applies to.&lt;/p&gt;

&lt;p&gt;Interestingly a 451 doesn’t necessarily mean that the resource being requested exists — if the legal reasoning behind denying it were removed, the resource might still not be there.&lt;/p&gt;

&lt;p&gt;Pretty cool.&lt;/p&gt;

&lt;h4&gt;
  
  
  418: I’m a Teapot
&lt;/h4&gt;

&lt;p&gt;Yeah you read that right. This client error responds to indicate that the server refuses to brew coffee because it is a teapot.&lt;/p&gt;

&lt;p&gt;Relax, It’s an April fools joke from 1998.&lt;/p&gt;

&lt;p&gt;Read more about it on the official &lt;a href="https://tools.ietf.org/html/rfc2324"&gt;Request for Comments&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  506: Variant Also Negotiates
&lt;/h4&gt;

&lt;p&gt;506 can be used to state that the server has an internal configuration error in which the chosen resource is configured to engage in a transparent content call itself, thus it’s not a proper end point in the negotiation process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experimental&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  508: Loop Detected
&lt;/h4&gt;

&lt;p&gt;Occurs when a server has encountered an infinite loop while processing a request — this is sent to indicate that the operation has failed.&lt;/p&gt;

&lt;p&gt;I personally haven’t seen this often as I find that when people detect infinite loops in their code they fix them or they’re uncaught leading to a timeout.&lt;/p&gt;

&lt;p&gt;There you have it, sort of interesting right?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoyed my ramblings? Follow me on&lt;/em&gt; &lt;a href="https://twitter.com/_ChrisGreg"&gt;&lt;em&gt;twitter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to hear more of my development tales or keep up with my side projects on my&lt;/em&gt; &lt;a href="http://chrisgregori.co.uk/"&gt;&lt;em&gt;personal site&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. 💻&lt;/em&gt;&lt;/p&gt;





</description>
      <category>programming</category>
      <category>https</category>
      <category>webdev</category>
      <category>httpstatuscode</category>
    </item>
    <item>
      <title>The highs and lows of using Lerna to manage your JavaScript projects</title>
      <dc:creator>Chris Gregori</dc:creator>
      <pubDate>Tue, 03 Oct 2017 14:30:17 +0000</pubDate>
      <link>https://dev.to/chriis/the-highs-and-lows-of-using-lerna-to-manage-your-javascript-projects-3bgg</link>
      <guid>https://dev.to/chriis/the-highs-and-lows-of-using-lerna-to-manage-your-javascript-projects-3bgg</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsJ3usVPNW83hftjs7V-dvA.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AsJ3usVPNW83hftjs7V-dvA.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Overview, pain points, highlights and tips&lt;/p&gt;

&lt;p&gt;Lerna is a tool for managing large scale JavaScript projects with multiple packages.&lt;/p&gt;

&lt;p&gt;Anyone that’s worked with huge projects that are made up of granular components or dependencies knows that it becomes a hassle to make updates to your work after a while. In the world of 2017 JavaScript we’re importing packages all over the place and Lerna is helping us manage them for our big projects at Yoox NET-A-PORTER.&lt;/p&gt;

&lt;h4&gt;
  
  
  Who’s using Lerna?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;BabelJS&lt;/li&gt;
&lt;li&gt;create-react-app&lt;/li&gt;
&lt;li&gt;react-router&lt;/li&gt;
&lt;li&gt;Jest&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lernajs.io/#users" rel="noopener noreferrer"&gt;And many, many more&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What it really does &amp;amp; why it’s great
&lt;/h4&gt;

&lt;p&gt;Lets start with an example.&lt;/p&gt;

&lt;p&gt;Imagine you have a React application with a Button component — this button component needs to use a Text component (granular but just humour me for the examples sake):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// inside the super-button NPM package + repo

import SuperText from 'super-text'

const SuperButton = props =\&amp;gt; (
 \&amp;lt;button\&amp;gt;
 \&amp;lt;SuperText value="Click me!" /\&amp;gt;
 \&amp;lt;/button\&amp;gt;
)

export default SuperButton

// inside the super-text NPM package + repo

const SuperText = props =\&amp;gt; (
 \&amp;lt;span\&amp;gt;
 {props.value}
 \&amp;lt;/span\&amp;gt;
)

export default SuperText
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each of these components live in their own repos and are their own NPM packages — they need to be maintained, versioned, and worked on by 20+ developers.&lt;/p&gt;

&lt;p&gt;Lets say we have a consuming application of both of these components — if we wanted to update both of these components as part of a feature then we would have to make the changes to each, update tests, update the versions, commit the changes, get them code reviewed, publish the packages, update the consuming application and use them — phew.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But wait!&lt;/strong&gt; You just realised your changes are slightly different to the requirements and/or it doesn’t work as expected — lets pretend these components are far more complicated or might involve complex styling etc. You’d have to redo that entire process again — if your team is busy maybe they won’t get around to code reviewing it, maybe you’ll be blocked for the next 2 hours and have to resort to reading Medium articles until they’ve unblocked you!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lerna to the rescue!&lt;/strong&gt; Lerna lets you construct your application into a very large repository of packages and apps (can all be renamed and configured); these apps are the consumers and the packages are the granular dependencies (SuperButton &amp;amp; SuperText above). When you’ve made all the changes required, you execute a command:&lt;/p&gt;

&lt;p&gt;$ lerna run bootstrap&lt;/p&gt;

&lt;p&gt;What this will do is go through all of your applications (in our self-named apps folder)and symlink each apps dependencies to any local version found inside the packages by using the respective packages name (and version!) in package.json. Any that aren’t found in packages will simply be installed from npm the same way you would anyway.&lt;/p&gt;

&lt;p&gt;This is huge — it allows massive refactoring, updating and feature enrichment without the &lt;em&gt;developer process headache&lt;/em&gt;. Make changes to your dependencies, bootstrap, check and implement them in your consumer apps and you’re done! Save the pull request until everything is ready.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why it can be annoying &amp;amp; how to mitigate the pain
&lt;/h4&gt;

&lt;p&gt;Sounds great right? We initially though so then we ran into some headaches porting our large app over — we’ve mostly solved all of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If you have a lot of dependencies in each application, bootstrapping can take a very long time.&lt;/strong&gt; 2017 web development usually means you have 500+ dependencies of all manner of packages running your application — whether it’s for a build step, transpilation, bundling, a reusable component or simply something to &lt;em&gt;left-pad&lt;/em&gt; your strings.
Mitigate this by moving all of your shared dependencies between apps &amp;amp; packages to a root package.json file and specify the --hoist flag in your bootstrap command. It’ll still take a while but it’ll greatly reduce the time taken.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests take a long time to run and lose syntax highlighting.&lt;/strong&gt;
The $ lerna run test command goes through each package and runs the test script declared in package.json — the issue here is it will spawn a test runner for every single instance it finds — in our case we had ~60 which ate our laptops up. It also meant that our syntax highlighting (passing/failing/warnings etc) were being omitted due to the test runs being spawn in seperate shell process.
Solve this by running your test runner from the root level with a config file there to specify which directory to find tests in — we use jest and the config file makes this all pretty easy. Our tests went from ~2m to run to ~15s and we got our colour coding back!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ways of working with one gigantic repo.&lt;/strong&gt;
We’re still solving this incrementally and will depend on your project, team structure and requirements — if you’re building a large shared platform of reusable, atomic components you sometimes ask yourselves ‘who owns this?’, often the answer is &lt;em&gt;everyone&lt;/em&gt; &lt;em&gt;should&lt;/em&gt; but things don’t always work out that way and is a talk for another blog post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re still getting used to Lerna, it’s been a rocky path of frustration but ultimately it’s worked out for the best. It was great for our project and it might just be great for yours.&lt;/p&gt;

&lt;h4&gt;
  
  
  Want to learn more about Lerna?
&lt;/h4&gt;

&lt;p&gt;Check out the &lt;a href="https://lernajs.io/" rel="noopener noreferrer"&gt;official site&lt;/a&gt; or check out the &lt;a href="https://github.com/lerna/lerna" rel="noopener noreferrer"&gt;github page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enjoyed my ramblings? Follow me on&lt;/em&gt; &lt;a href="https://twitter.com/_ChrisGreg" rel="noopener noreferrer"&gt;&lt;em&gt;twitter&lt;/em&gt;&lt;/a&gt; &lt;em&gt;to hear more of my development tales or keep up with my side projects on my&lt;/em&gt; &lt;a href="http://chrisgregori.co.uk/" rel="noopener noreferrer"&gt;&lt;em&gt;personal site&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. 💻&lt;/em&gt;&lt;/p&gt;




</description>
      <category>softwaredesignpatt</category>
      <category>lerna</category>
      <category>softwaredevelopment</category>
      <category>softwarearchitectur</category>
    </item>
  </channel>
</rss>
