<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Emmanuel Etti</title>
 <link href="https://emmanueletti.com/atom.xml" rel="self"/>
 <link href="https://emmanueletti.com/"/>
 <updated>2024-09-25T22:38:44+00:00</updated>
 <id>https://emmanueletti.com</id>
 <author>
   <name>Emmanuel Etti</name>
   <email>hello@emmanueletti.com</email>
 </author>

 
 <entry>
   <title>Shell Cheatsheet</title>
   <link href="https://emmanueletti.com/2023/06/01/shell-cheatsheet"/>
   <updated>2023-06-01T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/06/01/shell-cheatsheet</id>
   <content type="html">&lt;h2 id=&quot;scroll-through-vim-output-by-page&quot;&gt;Scroll through (vim) output by page&lt;/h2&gt;

&lt;p&gt;Instead of holding down up and down to scroll through a long page:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;space&lt;/code&gt; to move down by page&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt; to move back up by page&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;quickly-move-from-end-to-start-of-a-command-prompt&quot;&gt;Quickly move from end to start of a command prompt&lt;/h2&gt;

&lt;p&gt;Instead of holding down the left and right arrow keys to move through a command prompt&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CTRL + a&lt;/code&gt; to go to the start of the prompt&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CTRL + e&lt;/code&gt; to go to the end of a prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;search-through-a-directory-of-files-for-a-regex-string-content&quot;&gt;Search through a directory of files for a regex string content&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Hn&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;user.+account&apos;&lt;/span&gt; ./dir_path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;copy-all-the-file-contents-of-a-directory&quot;&gt;Copy all the file contents of a directory&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;find /home/vagrant/dotfiles &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; f &lt;span class=&quot;nt&quot;&gt;-print0&lt;/span&gt; | xargs &lt;span class=&quot;nt&quot;&gt;-0&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find&lt;/code&gt; with flags &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-type f -print0&lt;/code&gt; to list out all the files in the target directory with a null char delimiter instead of a new line&lt;/li&gt;
  &lt;li&gt;this allows for the selection of file names with whitespaces and such&lt;/li&gt;
  &lt;li&gt;pipe the results into &lt;a href=&quot;https://www.youtube.com/watch?v=rp7jLi_kgPg&quot;&gt;xgargs&lt;/a&gt; with flag &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-0&lt;/code&gt; telling it that the arguments are separated by null chars&lt;/li&gt;
  &lt;li&gt;xargs is like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.map&lt;/code&gt; on the Unix command line, it turns what has been piped into it into a list of arguments to then call the following command on each one&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;references-and-further-reading&quot;&gt;References and Further Reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://explainshell.com/&quot;&gt;Explain shell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Collection Of Helpful Guides, Talks, and Resources</title>
   <link href="https://emmanueletti.com/2023/05/22/collection-of-helpful-guides-and-resources"/>
   <updated>2023-05-22T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/05/22/collection-of-helpful-guides-and-resources</id>
   <content type="html">&lt;h2 id=&quot;guides&quot;&gt;Guides&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://railsnotes.xyz/blog/seed-your-database-with-the-faker-gem&quot;&gt;Speed up rails seeding&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.fastruby.io/blog/how-to-improve-debugging-skills-in-rails.html&quot;&gt;Ruby debugging tips and tricks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://discuss.rubyonrails.org/t/active-storage-in-production-lessons-learned-and-in-depth-look-at-how-it-works/83289&quot;&gt;Active storage in production: lessons learnt and in-depth look&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cpu.land/&quot;&gt;Undertstanding the CPU&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://code.avi.nyc/an-activestorage-s3-direct-uploader-part-1-the-drag-and-drop-interface&quot;&gt;Building a drag-and-drop file uploading to S3 using Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stevepolito.design/blog/rails-authentication-from-scratch&quot;&gt;Rails authentication from scratch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ankane/the-ultimate-guide-to-ruby-timeouts&quot;&gt;The ultimate guide to Ruby timeouts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ankane/secure_rails&quot;&gt;Best practices for running Rails in production&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ankane/production_rails/blob/master/Development.md&quot;&gt;Best practices for developing with Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ankane/production_rails/blob/master/Scaling.md&quot;&gt;Best practices for scaling Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://danielmiessler.com/p/vim/&quot;&gt;Learn VIM for the last time&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ombulabs.com/blog/learning/rails/nested-forms.html&quot;&gt;Nested forms in rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://justincypret.com/blog/validating-normalizing-and-formatting-phone-numbers-in-rails&quot;&gt;Validating, normalizing, and formatting phone numbers in rails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;interesting-talks&quot;&gt;Interesting talks&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=NLT7Qcn_PmI&quot;&gt;Jim Weirich - Grand unified theory of software development&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Jim_Weirich#Presentations&quot;&gt;Any talk by Jim Weirich&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;Search YouTube for Jim Weirich’s talks&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://island94.org/2023/05/whatever-you-do-don-t-autoload-rails-lib&quot;&gt;Don’t autoload rails &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/lib&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ankane/awesome-legal&quot;&gt;Awesome legal resources&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://ohshitgit.com/&quot;&gt;Oh Shit, Git!?!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://rubyhero.dev/?source=top_nav_blog_home&quot;&gt;Intermediate Rails articles&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reinteractive.com/articles/a-closer-look-at-n-plus-1&quot;&gt;Closer look at N+1 queries in rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.akshaykhot.com/page/2/&quot;&gt;Well written break down of rails things&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;security&quot;&gt;Security&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.bearer.com/blog/ultimate-ruby-rails-data-security&quot;&gt;Guide to rails security&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/eliotsykes/rails-security-checklist&quot;&gt;Rails security checklist&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/eliotsykes/rails-security-checklist&quot;&gt;Zen rails security checklist&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/pxlpnk/awesome-ruby-security&quot;&gt;Awesome Ruby security resources&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ankane/secure_rails&quot;&gt;Best practices for securing Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wafris.org/guides/ultimate-guide-to-rack-attack&quot;&gt;Ultimate guide to setting up rack_attack in Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cheatsheetseries.owasp.org/cheatsheets/Ruby_on_Rails_Cheat_Sheet.html&quot;&gt;OWASP Ruby on Rails Security Cheatsheet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://ankane.org/sensitive-data-rails&quot;&gt;Storing sensitive data in Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wafris.org/ip-lookup&quot;&gt;IP lookup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;ruby-tools&quot;&gt;Ruby tools&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://evilmartians.com/chronicles/gemfile-of-dreams-libraries-we-use-to-build-rails-apps&quot;&gt;The Evil Martian gemfile&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ruby-toolbox.com/&quot;&gt;The ruby toolbox&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gorails.com/tool_categories&quot;&gt;Gorails - ruby tools&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://awesome-ruby.com/&quot;&gt;Awesome ruby&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Rails Console Cheatsheet</title>
   <link href="https://emmanueletti.com/2023/05/20/rails-console-cheatsheet"/>
   <updated>2023-05-20T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/05/20/rails-console-cheatsheet</id>
   <content type="html">&lt;h2 id=&quot;see-all-the-methods-on-a-class-or-instance&quot;&gt;See All The Methods On A Class or Instance&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irb&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:001:0&amp;gt; User.methods
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This returns an array, which one can then do array things with, like filtering based
on a pattern match&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irb&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:001:0&amp;gt;  User.methods.grep&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;/string_pattern/&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;bg-light-yellow black ba pa2&quot;&gt;
  &lt;span class=&quot;fw6&quot;&gt;NOTE:&lt;/span&gt;
  The [ &lt;code&gt;Enumerable#grep&lt;/code&gt; ] method is super useful. Check out the ruby docs to see what it can do.
&lt;/div&gt;

&lt;p&gt;Or if you want a longer way of doing it…&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;irb&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:001:0&amp;gt;  User.methods.filter &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;|m| m.to_s.include?&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;string_pattern&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;finding-a-methods-source-location&quot;&gt;Finding A Methods Source Location&lt;/h2&gt;

&lt;p&gt;If rails constants/contexts need to be loaded, then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rails console&lt;/code&gt;, otherwise use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irb&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Find the source location for a method called on an instance:&lt;/span&gt;
irb&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:001:0&amp;gt; user &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; User.new&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;name: &lt;span class=&quot;s2&quot;&gt;&quot;John&quot;&lt;/span&gt;, email: &lt;span class=&quot;s2&quot;&gt;&quot;john@email.com&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
irb&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:001:0&amp;gt; user.method&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;:send_confirmation_instructions&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;.source_location
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/Users/etti/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/devise-4.8.1/lib/devise/models/confirmable.rb&quot;&lt;/span&gt;, 79]

&lt;span class=&quot;c&quot;&gt;# Find the source location for an instances method &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# but through its Class:&lt;/span&gt;
irb&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:001:0&amp;gt; User.instance_method&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;:confirm&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;.source_location
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/Users/etti/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/devise-4.8.1/lib/devise/models/confirmable.rb&quot;&lt;/span&gt;, 79]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Back in the normal shell, you can then use bundler to open the gems source code and then navigate to the
file and line number obtained from the previous command&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# This will open up your current version of the gem&lt;/span&gt;
bundler open devise
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;bg-light-yellow black ba pa2&quot;&gt;
  &lt;span class=&quot;fw6&quot;&gt;NOTE:&lt;/span&gt;
  To open up a gem&apos;s source code in general can run [ &lt;code&gt;gem open gem_name&lt;/code&gt; ] or [ &lt;code&gt;bundle open gem_name&lt;/code&gt; ] depending on what tool is managing the dependency.
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://boringrails.com/tips/bundle-open-debug-gems&quot;&gt;Reference: Search and debug ruby code with bundler open&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or if you want to do it an uglier waym, in the normal shell, you can take the path output,  use an editor like vscode to open up the source code file and then head down to the line number given.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;code /Users/etti/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/devise-4.8.1/lib/devise/models/confirmable.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.codynorman.com/ruby/rails_console_deep_dive/&quot;&gt;Rails console deep dive&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ruby Cheatsheet</title>
   <link href="https://emmanueletti.com/2023/05/15/ruby-cheatsheet"/>
   <updated>2023-05-15T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/05/15/ruby-cheatsheet</id>
   <content type="html">&lt;h2 id=&quot;debugging-ruby-code-with-bundler-open&quot;&gt;Debugging ruby code with bundler open&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundler open GEM-NAME
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will open up the source code of the gem installed using the editor set by the environment variables &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EDITOR&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BUNDLER_EDITOR&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can set breakpoints, change the source code, grep through it with your editor.&lt;/p&gt;

&lt;p&gt;Once debugging is finished run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundler pristine&lt;/code&gt; to reset any changes&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://boringrails.com/tips/bundle-open-debug-gems&quot;&gt;Reference: Search and debug ruby code with bundler open&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;placeholder-string-trick&quot;&gt;Placeholder String Trick&lt;/h2&gt;

&lt;p&gt;Ruby has a trick for creating placeholders within a string and then populating
the placeholders’ positions with an array of values.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;VERSE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;On the %s day of Christmas my true love gave to me: %s.&quot;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;VERSE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;first&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;a Partridge in a pair tree&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%&lt;/code&gt; inserts the array of values sequentially into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%s&lt;/code&gt; portions of the
text&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thought Shaping Articles, Content, And Resources</title>
   <link href="https://emmanueletti.com/2023/05/02/thought-shaping-resources"/>
   <updated>2023-05-02T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/05/02/thought-shaping-resources</id>
   <content type="html">&lt;h2 id=&quot;software-simplicity&quot;&gt;Software Simplicity&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.bradfieldcs.com/you-are-not-google-84912cf44afb&quot;&gt;You Are Not Google&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://grugbrain.dev/&quot;&gt;The Grug-Brained Developer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.cs.utexas.edu/~EWD/ewd03xx/EWD340.PDF&quot;&gt;The Humble Programmer By Dijkstra&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.bitecode.dev/p/hype-cycles&quot;&gt;Hype cycles&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=3wyd6J3yjcs&quot;&gt;The Silver Bullet Syndrome&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.entropywins.wtf/blog/2017/01/02/simple-is-not-easy/&quot;&gt;Simple Is Not Easy&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://boringrails.com/&quot;&gt;Boring Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://changelog.com/shipit/62&quot;&gt;Operational Simplicity Is A Gift To You&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://danluu.com/simple-architectures/&quot;&gt;Benefits of simple architectures&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nickcraver.com/blog/2016/02/17/stack-overflow-the-architecture-2016-edition/&quot;&gt;Stack Overflow’s 1 Web Server Architecture In 2016&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.c2.com/?DoSimpleThings&quot;&gt;Do Simple Things&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://renegadeotter.com/2023/09/10/death-by-a-thousand-microservices.html&quot;&gt;Death by a thousan microservices&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=SxdOUGdseq4&quot;&gt;Rich hickey - Simple made easy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;software-development-in-the-real-world&quot;&gt;Software Development In The Real World&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://vadimkravcenko.com/shorts/things-they-didnt-teach-you/&quot;&gt;Things they didn’t teach you about Software Engineering&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://vadimkravcenko.com/shorts/software-development-subjective/&quot;&gt;Software Development Is Subjective&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=UAzQZdttdsA&quot;&gt;Don’t Try To Remember Everything&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://vadimkravcenko.com/shorts/every-app-has-its-skeletons/&quot;&gt;Every App Has Its Skeletons&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://vadimkravcenko.com/shorts/being-an-amateur/&quot;&gt;Being An Amateur&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.simplethread.com/20-things-ive-learned-in-my-20-years-as-a-software-engineer/&quot;&gt;20 Lessons Learned From 20 Years Of Software Engineering&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://apenwarr.ca/log/20230415&quot;&gt;Apenwarr: Systems Design&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;problem-solving&quot;&gt;Problem Solving&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://ieftimov.com/posts/problem-solving-framework-principles-software-engineers/&quot;&gt;Problem-Solving Framework Principles For Software Engineers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=zssIhcAABCA&quot;&gt;Algorithmically Speaking with Elliott Jin of Triplebyte
(Podcast)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cerebralab.com/Imaginary_Problems_Are_the_Root_of_Bad_Software&quot;&gt;Imaginary Problems Are The Root Of Bad Software&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://cerebralab.com/Stop%20future%20proofing%20software&quot;&gt;Stop Future Proofing Software&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;productivity&quot;&gt;Productivity&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=c3pzcV9yi24&quot;&gt;How I Have Time For Everything (From A Principal At Amazon)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://maketime.blog/&quot;&gt;Make Time Framework&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;opinions-on-patterns-and-best-practices&quot;&gt;Opinions On Patterns And Best Practices&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.entropywins.wtf/blog/2017/09/06/the-fallacy-of-dry/&quot;&gt;The Fallacy Of Dry&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction&quot;&gt;Prefer Duplication Over Hasty Abstractions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;embracing-slow&quot;&gt;Embracing Slow&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://design.family/&quot;&gt;Slow Design Manifesto&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sive.rs/slow&quot;&gt;Derek Sivers Slow Thinking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Rails Database Migration Concepts</title>
   <link href="https://emmanueletti.com/2023/04/18/rails-migration-concepts"/>
   <updated>2023-04-18T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/18/rails-migration-concepts</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#how-rails-know-that-a-migration-has-run&quot;&gt;How Rails “Know” That A Migration Has Run&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://guides.rubyonrails.org/active_record_migrations.html&quot;&gt;Rails Guides: ActiveRecord
Migrations&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-rails-know-that-a-migration-has-run&quot;&gt;How Rails “Know” That A Migration Has Run&lt;/h2&gt;
</content>
 </entry>
 
 <entry>
   <title>Rails Database Migration Cheatsheet</title>
   <link href="https://emmanueletti.com/2023/04/18/rails-migration-cheatsheet"/>
   <updated>2023-04-18T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/18/rails-migration-cheatsheet</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#dangerous-migrations-for-large-scale-production-applications&quot;&gt;Dangerous Migrations (For Large Scale Production Applications)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cheatsheet&quot;&gt;Cheatsheet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#common-commands&quot;&gt;Common Commands&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#generate-a-migration&quot;&gt;Generate a migration&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#run-all-pending-rails-migrations&quot;&gt;Run all pending rails migrations&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#database-rollbacks&quot;&gt;Database rollbacks&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#breaking-down-common-database-migration-examples&quot;&gt;Breaking Down Common Database Migration Examples&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#creating-a-new-table&quot;&gt;Creating a new table&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#adding-a-foreign-key-reference-to-an-existing-table&quot;&gt;Adding a foreign key reference to an existing table&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#adding-a-foreign-key-reference-with-a-custom-column-name&quot;&gt;Adding a foreign key reference with a custom column name&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#alternative-syntax-for-creating-a-foreign-key-reference&quot;&gt;Alternative syntax for creating a foreign key reference&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#adding-or-removing-a-column-from-a-table&quot;&gt;Adding or removing a column from a table&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://guides.rubyonrails.org/active_record_migrations.html&quot;&gt;Rails Guides: ActiveRecord
Migrations&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;dangerous-migrations-for-large-scale-production-applications&quot;&gt;Dangerous Migrations (For Large Scale Production Applications)&lt;/h2&gt;

&lt;p&gt;Certain migrations can be dangerous to perform in production because of how long they
can take or how prone they are to causing exceptions if done improperly.&lt;/p&gt;

&lt;p&gt;During a long running migration, the database tables invovled are locked, thus blocking
requests to the database from the application.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strong_migrations&lt;/code&gt; gem is a helpful tool for catching “dangerous” database changes. The gems’ &lt;a href=&quot;https://github.com/ankane/strong_migrations#removing-a-column&quot;&gt;README examples&lt;/a&gt; do a great job of explaining why certain migrations are “dangerous” at scale.&lt;/p&gt;

&lt;p&gt;An alternative to using the gem is to perform any long-running/request-blocking migrations during periods of low request volume. Or to put the application in &lt;a href=&quot;https://gorails.com/tool_categories/maintenance-mode/tools&quot;&gt;maintenance mode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This does not avoid the other advantage of the gem, which is catching unsafe migrations that might need matching applciation layer changes.&lt;/p&gt;

&lt;h2 id=&quot;cheatsheet&quot;&gt;Cheatsheet&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.akshaykhot.com/rails-database-migrations-cheatsheet/#create-column&quot;&gt;Comprehensive rails migration cheatsheet&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;common-commands&quot;&gt;Common Commands&lt;/h2&gt;

&lt;h3 id=&quot;generate-a-migration&quot;&gt;Generate a migration&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bin/rails g migration AddColumnToTable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;run-all-pending-rails-migrations&quot;&gt;Run all pending rails migrations&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bin/rails db:migrate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To migrate a specific migration out of order&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake db:migrate:up &lt;span class=&quot;nv&quot;&gt;VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;20100905201547
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;database-rollbacks&quot;&gt;Database rollbacks&lt;/h3&gt;

&lt;p&gt;Important, after creating a new migration, perform a rollback to make sure the
migration is reversible&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bin/rails db:rollback
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rollback a certain number of migrations&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake db:rollback &lt;span class=&quot;nv&quot;&gt;STEP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Rollback only one specific migration (out of order) use:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake db:migrate:down &lt;span class=&quot;nv&quot;&gt;VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;20100905201547
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;breaking-down-common-database-migration-examples&quot;&gt;Breaking Down Common Database Migration Examples&lt;/h2&gt;

&lt;h3 id=&quot;creating-a-new-table&quot;&gt;Creating a new table&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUserTable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:full_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:encrypted_password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:admin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;default: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamps&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;add_index&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;unique: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_reference&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
      &lt;span class=&quot;ss&quot;&gt;foreign_key: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;on_delete: :cascade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;index: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;bg-light-yellow black ba pa2&quot;&gt;
  &lt;span class=&quot;fw6&quot;&gt;NOTE:&lt;/span&gt;
  Boolean columns should always have a `default: VALUE` and `null: false` constraint set
&lt;/div&gt;

&lt;h3 id=&quot;adding-a-foreign-key-reference-to-an-existing-table&quot;&gt;Adding a foreign key reference to an existing table&lt;/h3&gt;

&lt;div class=&quot;bg-light-yellow black ba pa2&quot;&gt;
  &lt;span class=&quot;fw6&quot;&gt;NOTE:&lt;/span&gt;
  For operations that change a pre-existing table, make sure to have
  the &lt;a href=&quot;https://github.com/ankane/strong_migrations&quot;&gt;strong_migrations gem&lt;/a&gt;
  installed or check the gems README for production-appropriate alternatives to
  long-running request-blocking operations. These examples here are meant to help
  understand what can be done, not necessarily recommendations for production.
&lt;/div&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddForeignKeyReference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_reference&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
              &lt;span class=&quot;ss&quot;&gt;foreign_key: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;on_delete: :cascade&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; 
              &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_reference :users&lt;/code&gt; denotes the table that the foreign key column will be
added to
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:organization&lt;/code&gt; denotes the resource the foreign key will target.&lt;/li&gt;
      &lt;li&gt;Rails magic will pluralize this input to infer the table name &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;organizations&lt;/code&gt; and add the suffix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_id&lt;/code&gt; to infer the column name &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;organization_id&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;Scroll down to see how to add a foreign key to a table but specify the column name&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foreign_key: { on_delete: cascade }&lt;/code&gt; tells the database to also delete child
records (users) with foreign keys equal to a deleted parent record id
(organization)
    &lt;ul&gt;
      &lt;li&gt;If this bevaviour is not wanted, then use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foreign_key: true&lt;/code&gt; to only add
the &lt;a href=&quot;https://guides.rubyonrails.org/active_record_migrations.html#foreign-keys&quot;&gt;referential db
constraint&lt;/a&gt;
that checks to make sure that the value is a valid id from the parent table&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;It is not necessary to specify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index: true&lt;/code&gt; when creating a reference. Rails will add the creation SQL to the end query by default
    &lt;ul&gt;
      &lt;li&gt;Creating an index for the foreign key is a performance optimization that for all the SQL queries generated by ActiveRecord when using association code like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user.organization&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;adding-a-foreign-key-reference-with-a-custom-column-name&quot;&gt;Adding a foreign key reference with a custom column name&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddForeignKeyReference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_reference&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo_bar_org&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
      &lt;span class=&quot;ss&quot;&gt;foreign_key: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;to_table: :organizations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;on_delete: :cascade&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; 
      &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;alternative-syntax-for-creating-a-foreign-key-reference&quot;&gt;Alternative syntax for creating a foreign key reference&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUserTable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:full_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
      
      &lt;span class=&quot;c1&quot;&gt;# yada yada yada ...&lt;/span&gt;
      
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;references&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;foreign_key: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;on_delete: :cascade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; 
                                  &lt;span class=&quot;ss&quot;&gt;index: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;timestamps&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;adding-or-removing-a-column-from-a-table&quot;&gt;Adding or removing a column from a table&lt;/h3&gt;

&lt;p&gt;Adding a column&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddPartNumberToProducts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:part_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Removing a column&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RemovePartNumberFromProducts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;remove_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:products&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:part_number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Understanding New Technologies</title>
   <link href="https://emmanueletti.com/2023/04/17/understanding-new-technologies"/>
   <updated>2023-04-17T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/17/understanding-new-technologies</id>
   <content type="html">&lt;p&gt;As a software developer, it is important to continually cultivate an
understanding of the tools available in the engineering toolbox. When faced with
a problem, a developer with a broad landscape is better able to pick the most
appropriate tool for the problem and constraints at hand.&lt;/p&gt;

&lt;p&gt;But if one is not intentional about how they explore new technologies, they can
fall into the trap of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Chasing after industry hype&lt;/li&gt;
  &lt;li&gt;Choosing solutions based on popularity&lt;/li&gt;
  &lt;li&gt;Not taking tradeoffs into account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To prevent that, the following is a framework for learning about new (and
established) technologies in a way that highlights the context and trade-offs
behind them.&lt;/p&gt;

&lt;h2 id=&quot;first-explore-the-questions&quot;&gt;First, explore the questions&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;What problem was the technology created to solve?&lt;/li&gt;
  &lt;li&gt;What is the historical context of the technology? (what was going on around
the time of the technology’s creation)&lt;/li&gt;
  &lt;li&gt;What are the alternative ways of solving the same problem?&lt;/li&gt;
  &lt;li&gt;What are the trade-offs between the other options and this technology?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;then-go-beyond-the-surface-level&quot;&gt;Then go beyond the surface level&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Read the paper, source code, docs, etc. to learn how the technology works
under the hood&lt;/li&gt;
  &lt;li&gt;Do a crash course&lt;/li&gt;
  &lt;li&gt;Independently build 1-2 projects with the technology&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the end of the process, summarize the key learnings in a technical note. This
prevents one from trying to memorize everything. Eventually, you may forget the
details of what you learned. But when a problem arises that triggers the memory
of learning the tool, you can go back to the note and asses whether the tool is
a good fit for the problem.&lt;/p&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.bradfieldcs.com/you-are-not-google-84912cf44afb&quot;&gt;You Are Not Google&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>SQL Cheatsheet</title>
   <link href="https://emmanueletti.com/2023/04/17/sql-cheatsheet"/>
   <updated>2023-04-17T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/17/sql-cheatsheet</id>
   <content type="html">&lt;h2 id=&quot;debugging-duplicates-in-a-dataset&quot;&gt;Debugging Duplicates In A Dataset&lt;/h2&gt;

&lt;p&gt;Sometimes you are working on a query and you want to debug whether there are
duplicates in your table.&lt;/p&gt;

&lt;div class=&quot;language-sql highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;select&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;having&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The query will show all the rows (grouped by id) with counts greater than 1.&lt;/p&gt;

&lt;p&gt;Unintentional duplicates can occur after a join. Instead of fixing this by
using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;select distinct&lt;/code&gt; (which is a code smell), try to figure out
&lt;em&gt;why&lt;/em&gt; the duplication is happening.&lt;/p&gt;

&lt;p&gt;Once you find the rows with duplicates, you can then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;select *&lt;/code&gt; for those
records to see if there is any relationship between them that explains the
duplication.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Rails Commands Cheatsheet</title>
   <link href="https://emmanueletti.com/2023/04/16/rails-commands-cheatsheet"/>
   <updated>2023-04-16T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/16/rails-commands-cheatsheet</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#general-guides&quot;&gt;General Guides&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#destroy-associated-records-when-parent-records-are-deleted&quot;&gt;Destroy Associated Records When Parent Records Are Deleted&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#generators&quot;&gt;Generators&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#generate-the-scaffold-for-a-model&quot;&gt;Generate The Scaffold For A Model&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#generate-a-rails-model&quot;&gt;Generate A Rails Model&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#model-validations&quot;&gt;Model Validations&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#validate-email-format&quot;&gt;Validate email format&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#misc&quot;&gt;Misc&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#a-nicer-print-out-of-rails-routes&quot;&gt;A Nicer Print Out Of Rails Routes&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#see-all-available-rake-tasks&quot;&gt;See all available rake tasks&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#implementation-guides&quot;&gt;Implementation Guides&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#additional-resources&quot;&gt;Additional resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;general-guides&quot;&gt;General Guides&lt;/h2&gt;

&lt;h3 id=&quot;destroy-associated-records-when-parent-records-are-deleted&quot;&gt;Destroy Associated Records When Parent Records Are Deleted&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;dependent: :destroy_all&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Warning, &lt;a href=&quot;https://medium.com/@wkhearn/delete-vs-destroy-does-it-even-matter-8cb4db6aa660&quot;&gt;there is a
difference&lt;/a&gt;
between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#delete&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#destroy&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;generators&quot;&gt;Generators&lt;/h2&gt;

&lt;h3 id=&quot;generate-the-scaffold-for-a-model&quot;&gt;Generate The Scaffold For A Model&lt;/h3&gt;

&lt;p&gt;The command format is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rails g scaffold &amp;lt;name of model&amp;gt; &amp;lt;model attributes&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bin/rails g scaffold ModelName name:string email:string description:text price:decimal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;generate-a-rails-model&quot;&gt;Generate A Rails Model&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; bin/rails g model ModelName name:string email:string description:text price:decimal seller_id:integer img_url:string
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can undo the generation with&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bin/rails destroy model ModelName name:string email:string description:text price:decimal seller_id:integer img_url:string
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;model-validations&quot;&gt;Model Validations&lt;/h2&gt;

&lt;h3 id=&quot;validate-email-format&quot;&gt;Validate email format&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;validates&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;presence: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;uniqueness: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Uses a constant built into URI in the standard ruby library&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;format: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;with: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;URI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;MailTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;EMAIL_REGEXP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;misc&quot;&gt;Misc&lt;/h2&gt;

&lt;h3 id=&quot;a-nicer-print-out-of-rails-routes&quot;&gt;A Nicer Print Out Of Rails Routes&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rails routes &lt;span class=&quot;nt&quot;&gt;--expanded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Can pipe into grep to search for specific string patterns&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rails routes &lt;span class=&quot;nt&quot;&gt;--expended&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;SEARCH_PATTERN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;see-all-available-rake-tasks&quot;&gt;See all available rake tasks&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rake &lt;span class=&quot;nt&quot;&gt;--tasks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;implementation-guides&quot;&gt;Implementation Guides&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://stevepolito.design/blog/rails-authentication-from-scratch&quot;&gt;Rails authentication from
scratch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=eK_JVdWOssI&quot;&gt;Lifecycle Of A Request In Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://thoughtbot.com/upcase/videos/rack&quot;&gt;What Is Rack&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://leahneukirchen.org/blog/archive/2007/02/introducing-rack.html&quot;&gt;Introducing Rack&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Big idea: Rack is just 2 things
    &lt;ul&gt;
      &lt;li&gt;A convention / agreed-upon protocol of how ruby “applications” should be structured so that web servers know what to expect
        &lt;ul&gt;
          &lt;li&gt;Framework developers can implement the agreed-upon Rack specs/interface that web servers would build their interface for&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;A gem with a library of helper methods, modules and middleware for framework developers to use if they want
        &lt;ul&gt;
          &lt;li&gt;Instead of each framework developer building the Rack specs/interface from scratch every time, they can use Rack as a gem with all the middleware and utilities to act as the middle layer between the webservers and the framework&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Protecting Data Integrity with Database Level Constraints</title>
   <link href="https://emmanueletti.com/2023/04/16/data-integrity-with-database-constraints"/>
   <updated>2023-04-16T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/16/data-integrity-with-database-constraints</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#the-importance-of-database-level-constraints&quot;&gt;The importance of database-level constraints&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#common-constraints&quot;&gt;Common constraints&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#making-sure-specified-attributes-on-records-are-unique&quot;&gt;Making sure specified attributes on records are unique&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#making-sure-a-column-is-never-null&quot;&gt;Making sure a column is never null&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#validate-based-on-boolean-expressions&quot;&gt;Validate based on boolean expressions&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#make-sure-associated-child-records-are-deleted-when-the-parent-record-is-deleted&quot;&gt;Make sure associated child records are deleted when the parent record is deleted&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#additional-resources&quot;&gt;Additional resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-importance-of-database-level-constraints&quot;&gt;The importance of database-level constraints&lt;/h2&gt;

&lt;p&gt;Even though Rails comes with a way to add validations on Models it’s still a
great idea to add database-level constraints as a backup to the
application-level constraints (rails model validations). This helps protect
database integrity when validations somehow get skipped.&lt;/p&gt;

&lt;p&gt;Scaled applications with multiple application instances can undermine
validations due to &lt;a href=&quot;https://thoughtbot.com/blog/the-perils-of-uniqueness-validations&quot;&gt;race
conditions&lt;/a&gt;.
And developers can use methods that bypass ActiveRecord callbacks (ie.
validations)&lt;/p&gt;

&lt;h2 id=&quot;common-constraints&quot;&gt;Common constraints&lt;/h2&gt;

&lt;h3 id=&quot;making-sure-specified-attributes-on-records-are-unique&quot;&gt;Making sure specified attributes on records are unique&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Model validation&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;validates&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;uniqueness: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Database constraint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When creating the table for the first time&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUsers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:another_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Single attribute email to be unique throughout the table&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;unique: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Combination of attributes to be unique throughout the table&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:another_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;unique: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding to an existing table&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddUniqueIndexToUsers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_index&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:another_attribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;unique: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;making-sure-a-column-is-never-null&quot;&gt;Making sure a column is never null&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Model validation&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;validates&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;presence: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Database constraint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When creating the table for the first time&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUsers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding to an existing table&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddUniqueIndexToUsers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;change_column&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;null: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;validate-based-on-boolean-expressions&quot;&gt;Validate based on boolean expressions&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS&quot;&gt;Check
constraints&lt;/a&gt;
allow you to define boolean expressions that must return truthy before a record
can be saved.&lt;/p&gt;

&lt;p&gt;In the model, you can have a validation to protect the data integrity of your
attributes&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Invoice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;validates&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;numericality: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;greater_than_or_equal_to: &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then back this up on the database level with a check constraint&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddAmountCheckToInvoices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_check_constraint&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:invoices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;amount &amp;gt;= 0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;amount_non_negative&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now a database error is thrown if somehow application level validations are
skipped&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Skip validations (don&apos;t try this at home)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invoice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1200&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invoice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;validate: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;PG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;CheckViolation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ERROR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;relation&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;invoices&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;violates&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;constraint&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;amount_non_negative&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;StatementInvalid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;make-sure-associated-child-records-are-deleted-when-the-parent-record-is-deleted&quot;&gt;Make sure associated child records are deleted when the parent record is deleted&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Model-level&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;dependent: :destroy_all&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Database-level&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When creating the table for the first time&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateUsers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;create_table&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;references&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;foreign_key: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;on_delete: :cascade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding to an existing table&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AddForeignKeyToUsers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;add_reference&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:organization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;foreign_key: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;on_delete: :cascade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Other options for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_reference&lt;/code&gt; in Rails migration&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null: false&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index: true&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tradeoff&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since the database will delete the child records automatically without reaching out to the application, any delete callbacks placed on child record models will be ignored.&lt;/p&gt;

&lt;p&gt;If you have specified that child records also delete certain other records when they are deleted, you have to be careful to add those constraints at the db level as well.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gorails.com/forum/rails-db-dependent-destroy-vs-cascade-delete&quot;&gt;Chris Oliver from GoRails recommends&lt;/a&gt; only relying on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dependent: :destroy&lt;/code&gt; which is slower but will make sure application-level logic is run after deletions (since the db will call back to the application).&lt;/p&gt;

&lt;p&gt;Even the &lt;a href=&quot;https://guides.rubyonrails.org/active_record_migrations.html#active-record-and-referential-integrity&quot;&gt;official Rails guide&lt;/a&gt; argues that data integrity logic should belong in your models. Seems that each use case should decide whether a model only or model + db constaints approach is best.&lt;/p&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://boringrails.com/tips/rails-check-constraints-database-validations&quot;&gt;Boring Rails: Database Level Check
Constraints&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://thoughtbot.com/blog/validation-database-constraint-or-both&quot;&gt;Thoughtbot: Validation Database Constraint Or
Both&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://guides.rubyonrails.org/active_record_validations.html#uniqueness&quot;&gt;Rails Guides: Active Record
Validations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.postgresql.org/docs/current/ddl-constraints.html&quot;&gt;Postgres Database
Constraint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Git Concepts</title>
   <link href="https://emmanueletti.com/2023/04/15/git-concepts"/>
   <updated>2023-04-15T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/15/git-concepts</id>
   <content type="html">&lt;h2 id=&quot;what-even-is-head&quot;&gt;What Even Is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt;?&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; is a symbolic reference pointing to your current place in the git
history. During normal state, this points to the latest commit on the branch you
are on (the tip of the branch).&lt;/p&gt;

&lt;p&gt;When in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;detached HEAD&lt;/code&gt; state, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; points to a specific commit SHA.&lt;/p&gt;

&lt;p&gt;You can see what HEAD is currently pointing to by running&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; .git/HEAD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;git enters detached head state when you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;checkout a specific commit SHA&lt;/li&gt;
  &lt;li&gt;checkout a remote branch without fetching first&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;git-reflog-is-a-magical-time-machine&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt; Is A Magical Time Machine&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Background context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After finishing up a feature, passing review, and getting ready to ship to prod, I squashed a set of 7-ish commits and rebased onto main to clean up the branch.&lt;/p&gt;

&lt;p&gt;Since this changes the git history, I  forced pushed my changes into the remote, which forcefully replaced remote with my work.&lt;/p&gt;

&lt;p&gt;Turns out something went wrong in my rebase and a test file for the feature I just completed (a days worth of work) had been deleted during the process. I had no copy of the commit introducing the test file in my local and no copy in the remote.&lt;/p&gt;

&lt;p&gt;Turns out &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt; was able to help me find the SHA of the commit where the test file was. I checked out that commit SHA and copied the test file into my squashed feature branch. I probably could have used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git cherrypick&lt;/code&gt; but that is a lesson for another day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reflog&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The reflog is a log of all the moves &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt; has made in your local repository. Every time you switch branches, start a rebase, merge branches, go into detached head state, etc. the reflog keeps an entry of this movement. Each entry includes the commit hash, and a message that contains a few other infos (like the branch name you switched to). This data is stored in your projects local &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;The reason why it’s possible to restore a messed-up repository with reflog is because git keeps those commit hashes. As long as there is &lt;em&gt;some&lt;/em&gt; reference to a commit &lt;em&gt;somewhere&lt;/em&gt; in the repo, Git won’t forget about that commit.&lt;/p&gt;

&lt;p&gt;As long as you are following good commit practises - commiting often, committing atomically - it’s near impossible to have something be lost forever.&lt;/p&gt;

&lt;p&gt;Just don’t delete your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; directory, the reflof of all your local movements will &lt;strong&gt;NOT&lt;/strong&gt; be in the remote repo.&lt;/p&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=_VhF-ojp-fk&quot;&gt;Git Reflog Explained Really Really
Well&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://css-tricks.com/using-the-reflog-to-restore-lost-commits/&quot;&gt;Another Example Driven Explanation Of Git
Reflog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://hackernoon.com/time-to-rewrite-your-git-history-effectively-with-git-reflog&quot;&gt;Detailed Writeup Of Git
Reflog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ocpsoft.org/tutorials/git/use-reflog-and-cherry-pick-to-restore-lost-commits/&quot;&gt;Git Reflog And Git Cherry Pick To Restore Lost
Commits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.atlassian.com/git/tutorials/rewriting-history&quot;&gt;Rewriting History&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Git Cheatsheet</title>
   <link href="https://emmanueletti.com/2023/04/15/git-cheatsheet"/>
   <updated>2023-04-15T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/15/git-cheatsheet</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#clean-up-local-branches&quot;&gt;Clean up local branches&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#reset-a-commit-from-head&quot;&gt;Reset a commit from HEAD&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#edit-the-changes-within-a-commit-without-destroying-the-commit&quot;&gt;Edit the changes within a commit without destroying the commit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#un-staging-a-file&quot;&gt;Un-staging a file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#show-a-condensed-log-of-commits&quot;&gt;Show a condensed log of commits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#show-a-log-of-commits-with-cool-graphs&quot;&gt;Show a log of commits with cool graphs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#compare-the-changes-between-commits&quot;&gt;Compare the changes between commits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#further-readings&quot;&gt;Further readings&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;clean-up-local-branches&quot;&gt;Clean up local branches&lt;/h2&gt;

&lt;p&gt;You’ve been working hard and now you have a bunch of local feature branches that
you don’t need anymore. Instead of running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git branch -D&lt;/code&gt; on each one.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git checkout main

git fetch

git branch &lt;span class=&quot;nt&quot;&gt;--merged&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-vE&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;(\*|main|master)&apos;&lt;/span&gt; | xargs git branch &lt;span class=&quot;nt&quot;&gt;-D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git checkout main&lt;/code&gt; switches the current branch to “main”. This assumes that the “main” branch already exists in the repository.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git fetch&lt;/code&gt; downloads the latest changes from the remote repository to your local repository. This ensures that you have an up-to-date list of branches that have been merged into the “main” branch.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git branch --merged&lt;/code&gt; lists all the branches that have been merged into the current branch.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep -vE &apos;(\*|main|master)&apos;&lt;/code&gt; filters out the current branch (*), as well as any branches named “main” or “master”. The explicit filtering of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; is paranoid insurance … just in case the initial checkout didn’t work for some reason.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xargs git branch -D&lt;/code&gt; passes each of the remaining branch names to the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git branch -D&lt;/code&gt;, which deletes them one by one. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xargs&lt;/code&gt; is like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; method in a Unix command line.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;reset-a-commit-from-head&quot;&gt;Reset a commit from HEAD&lt;/h2&gt;

&lt;p&gt;You just committed some changes but want to undo that commit for whatever
reason. Maybe you’ve committed to the wrong branch, or you forgot to add another
change, etc.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git reset HEAD~1 &lt;span class=&quot;nt&quot;&gt;--soft&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This &lt;strong&gt;will destroy&lt;/strong&gt; that git commit! But with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--soft&lt;/code&gt; flag the changes in
that commit will be preserved for you to create a new commit (or set of commits)
from.&lt;/p&gt;

&lt;p&gt;If you want to reset the last &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; commits (from the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HEAD&lt;/code&gt;) while saving
the changes from those 5 commits. Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt; with whatever number you want to
go back.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git reset HEAD~N &lt;span class=&quot;nt&quot;&gt;--soft&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want to reset changes on the branch back to a specific commit from HEAD
(while still keeping the changes)&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git reset &lt;span class=&quot;nt&quot;&gt;--soft&lt;/span&gt; &amp;lt;commit &lt;span class=&quot;nb&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Warning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This action re-writes the git history and should be done with care. As a rule,
do not make changes to the git history on work that has already gone public.
This breaks things for other devs working on that branch. Only do this if:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;you haven’t pushed the changes to the remote repository&lt;/li&gt;
  &lt;li&gt;you know you are the only one working on that branch&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;edit-the-changes-within-a-commit-without-destroying-the-commit&quot;&gt;Edit the changes within a commit without destroying the commit&lt;/h2&gt;

&lt;p&gt;You want to add some new content or edit some of the files changed in a specific
commit.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git rebase &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; main OR SHA_OF_SPECIFIC_COMMIT_TO_REBASH_OFF_OF
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will open up an interactive rebase session where you will see all the
commits your branch adds on top of the tip of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; or a specified commit SHA.&lt;/p&gt;

&lt;p&gt;For each commit, you will have a set of actions you can take. Choosing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edit&lt;/code&gt;
will place you into that commit where you change the state of the files within
that commit. You can create new files, change modifications, delete files, etc.&lt;/p&gt;

&lt;p&gt;Be careful with the changes, as you may create git conflicts with any following
commits.&lt;/p&gt;

&lt;p&gt;Once changes have been made:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;verify the changes made with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git status&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git diff&lt;/code&gt;, or using the vscode
source control UI run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add . OR specify-the-files-to-add&lt;/code&gt; to add the
changes, and then continue the rebase&lt;/li&gt;
  &lt;li&gt;run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add . OR specify-the-files-to-add&lt;/code&gt; (be careful with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add .&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit --amend&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;since we did not destroy the commit with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset HEAD~&lt;/code&gt;, the commit still
exists but now we want to amend all these new changes to that commit&lt;/li&gt;
      &lt;li&gt;If we did reset the commit (destroy it) &lt;strong&gt;DO NOT&lt;/strong&gt; RUN &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit --amend&lt;/code&gt;
as this will amend all your changes to the last previous commit which is NOT
the old commit anymore since we blew that up with the reset&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;But if you want all the new changes in their own atomic commit then do the
normal flow of
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add .&lt;/code&gt; (use carefully)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once complete, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase --continue&lt;/code&gt; to continue the rebase.&lt;/p&gt;

&lt;p&gt;Remove the changes made to a file&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git status &lt;span class=&quot;c&quot;&gt;# to get the path names of the files added&lt;/span&gt;
git reset &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; FILE_PATH_NAME &lt;span class=&quot;c&quot;&gt;# to remove the file&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;FILE_PATH_NAME &lt;span class=&quot;c&quot;&gt;# if you need to delete the file all together&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;un-staging-a-file&quot;&gt;Un-staging a file&lt;/h2&gt;

&lt;p&gt;You yolo’d and used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git add .&lt;/code&gt; without checking the changes included. But thankfully you have not committed yet.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git status &lt;span class=&quot;c&quot;&gt;# get the name and path of the file&lt;/span&gt;
git reset &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; FILE_PATH &lt;span class=&quot;c&quot;&gt;# unstage the file from staging&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;show-a-condensed-log-of-commits&quot;&gt;Show a condensed log of commits&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;show-a-log-of-commits-with-cool-graphs&quot;&gt;Show a log of commits with cool graphs&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git log &lt;span class=&quot;nt&quot;&gt;--oneline&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--decorate&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--color&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--graph&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;compare-the-changes-between-commits&quot;&gt;Compare the changes between commits&lt;/h2&gt;

&lt;p&gt;Compare the current commit and n number of commits back&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git diff HEAD~n HEAD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Compare the current commit with the tip of main&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git diff HEAD main
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;further-readings&quot;&gt;Further readings&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.freecodecamp.org/news/how-to-recover-a-deleted-file-in-git/&quot;&gt;Freecodecamp - How To Recover A Deleted File In Git&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://ohshitgit.com/&quot;&gt;Oh Shit, Git!?!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://explainshell.com/&quot;&gt;Explain Shell Commands&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Personal Software Developer Growth Plan</title>
   <link href="https://emmanueletti.com/2023/04/07/personal-software-developer-growth-plan"/>
   <updated>2023-04-07T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/07/personal-software-developer-growth-plan</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#resources&quot;&gt;Resources&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#problem-solving-practise&quot;&gt;Problem solving practise&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#learning-platforms&quot;&gt;Learning platforms&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#practice&quot;&gt;Practice&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#fundamentals-of-a-full-stack-web-developer&quot;&gt;Fundamentals of a full stack web developer&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#how-the-web-works&quot;&gt;How the web works&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#full-stack-web-development&quot;&gt;Full stack web development&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#web-relevant-programming-languages&quot;&gt;Web relevant programming languages&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#battle-tested-web-framework-rails&quot;&gt;Battle-tested web framework (rails)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#front-end-library-react&quot;&gt;Front-end library (react)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#databases-and-datastructures&quot;&gt;Databases and datastructures&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#core-tools&quot;&gt;Core tools&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#fundamentals-of-software-craftsmanship&quot;&gt;Fundamentals of software craftsmanship&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#general-craft&quot;&gt;General craft&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#object-oriented-programming&quot;&gt;Object Oriented Programming&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#design-and-software-architecture&quot;&gt;Design and software architecture&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#refactoring&quot;&gt;Refactoring&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#testing&quot;&gt;Testing&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#performance&quot;&gt;Performance&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#devops&quot;&gt;DevOps&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#fundamentals-of-computer-science&quot;&gt;Fundamentals of computer science&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#resources-1&quot;&gt;Resources&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#low-level-programming&quot;&gt;Low-level programming&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#healthy-reminders-and-inspiration&quot;&gt;Healthy reminders and inspiration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Knowing every framework, tool, language and library is not possible, nor is it
the goal of a software engineer. This is a continually improving &lt;strong&gt;personal&lt;/strong&gt;
plan to help me grow as an engineer capable of solving meaningful problems.&lt;/p&gt;

&lt;h3 id=&quot;resources&quot;&gt;Resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://roadmap.sh/roadmaps&quot;&gt;Software Engineering Roadmaps&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://lbacaj.gumroad.com/l/career-advice-for-engineers&quot;&gt;Timeless Career Advice For Engineers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://learninpublic.org/&quot;&gt;The Coding Career Handbook&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mentorcruise.com/filter/engineering/&quot;&gt;Mentor Cruise&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://adplist.org/&quot;&gt;ADP List&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;problem-solving-practise&quot;&gt;Problem solving practise&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://press.princeton.edu/books/paperback/9780691164076/how-to-solve-it&quot;&gt;George Polya - How To Solve It&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://projecteuler.net/&quot;&gt;Project Euler&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://exercism.org/&quot;&gt;Exercism&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://leetcode.com/&quot;&gt;Leetcode&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.frontendmentor.io/&quot;&gt;Frontend Mentor challenges&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;learning-platforms&quot;&gt;Learning platforms&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://thoughtbot.com/upcase/&quot;&gt;Thoughtbot Upcase&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://graceful.dev/&quot;&gt;Graceful Dev&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gorails.com/users/sign_in&quot;&gt;GoRails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.freecodecamp.org/&quot;&gt;Freecodecamp&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.macournoyer.com/products/&quot;&gt;Macournoyer resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;practice&quot;&gt;Practice&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Build, build, build, then get feedback&lt;/li&gt;
  &lt;li&gt;Build independent projects&lt;/li&gt;
  &lt;li&gt;Read the source code&lt;/li&gt;
  &lt;li&gt;Peek under the hood&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;fundamentals-of-a-full-stack-web-developer&quot;&gt;Fundamentals of a full stack web developer&lt;/h2&gt;

&lt;p&gt;The goal is to be able to create and deploy an end to end web application from scratch; as well as contribute effectively to an established project.&lt;/p&gt;

&lt;h3 id=&quot;how-the-web-works&quot;&gt;How the web works&lt;/h3&gt;

&lt;p&gt;Intro&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.freecodecamp.org/news/how-the-web-works-a-primer-for-newcomers-to-web-development-or-anyone-really-b4584e63585c/&quot;&gt;Freecodecamp - How The Web Works&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=2JYT5f2isg4&quot;&gt;Freecodecamp - HTTP Networking course&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.kevinpowell.co/courses/&quot;&gt;Kevin Powell - Responsive Design Bootcamp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deeper&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.freecodecamp.org/news/api-integration-patterns/&quot;&gt;Freecodecamp - API Integration Patterns&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gorails.com/episodes/ruby-http-server-from-scratch&quot;&gt;GoRails - Build a Multithreaded HTTP Server From Scratch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.freecodecamp.org/news/tag/rest-api/&quot;&gt;Freecodecamp - REST API&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://book.productionreadygraphql.com/&quot;&gt;Production Ready GraphQL (Book)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;full-stack-web-development&quot;&gt;Full stack web development&lt;/h3&gt;

&lt;p&gt;Intro&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://zerotomastery.io/courses/coding-bootcamp/&quot;&gt;ZTM - Complete Web Developer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zerotomastery.io/courses/junior-to-senior-web-developer-roadmap/&quot;&gt;ZTM - Junior to Senior Web Developer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://youmightnotneedjs.com/&quot;&gt;You Might Not Need JS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://leanwebclub.com/&quot;&gt;Chris Ferdinandi - Lean Web Club&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deeper&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.macournoyer.com/products/&quot;&gt;Marc-Andre Courmoyer’s advanced resources&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.macournoyer.com/products/&quot;&gt;Destroy All Software - From Scratch series&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;web-relevant-programming-languages&quot;&gt;Web relevant programming languages&lt;/h3&gt;

&lt;p&gt;Ruby&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.rubykoans.com/&quot;&gt;Ruby Koans&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://learncodethehardway.org/ruby/&quot;&gt;Zed Shaw - Learn Ruby The Hard Way&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.manning.com/books/the-well-grounded-rubyist&quot;&gt;David Black - The Well-Grounded Rubyist&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://createyourproglang.com/&quot;&gt;Build Your Own Programming Language&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Javascript&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.executeprogram.com/courses&quot;&gt;Execute Program - Typescrypt and Javascript Courses&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zerotomastery.io/courses/learn-node-js/&quot;&gt;ZTM - Node.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zerotomastery.io/courses/advanced-javascript-concepts/&quot;&gt;ZTM - Advanced Javascript&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/getify/You-Dont-Know-JS&quot;&gt;Kyle Simpson - You Don’t Know JS Yet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;battle-tested-web-framework-rails&quot;&gt;Battle-tested web framework (rails)&lt;/h3&gt;

&lt;p&gt;Intro&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://pragmaticstudio.com/rails&quot;&gt;Pragmatic Studio - Rails 7&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pragmaticstudio.com/hotwire-rails&quot;&gt;Pragmatic Studio - Rails Hotwire&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Chad Pytel - Rails Antipatterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deeper&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://owningrails.com/&quot;&gt;Marc-Andre Courmoyer - Owning Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.refactoringrails.io/&quot;&gt;Refactoring Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://rebuilding-rails.com/&quot;&gt;Noah Gibbs - Rebuilding Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.destroyallsoftware.com/screencasts/catalog&quot;&gt;Destroy All Software - Web Framework From Scratch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Paul Dix - Service-Oriented Design with Ruby and Rails&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://products.arkency.com/domain-driven-rails/&quot;&gt;Arkency - Domain Driven Rails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;front-end-library-react&quot;&gt;Front-end library (react)&lt;/h3&gt;

&lt;p&gt;Intro&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://epicreact.dev/&quot;&gt;Kent C Dodds - Epic React&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zerotomastery.io/courses/learn-react/&quot;&gt;ZTM - React&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deeper&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://pomb.us/build-your-own-react/&quot;&gt;Rebuilding React&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Ilya Grigorik - High Performance Browser Networking&lt;/li&gt;
  &lt;li&gt;Michailia Verou - CSS Secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;databases-and-datastructures&quot;&gt;Databases and datastructures&lt;/h3&gt;

&lt;p&gt;Intro&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.executeprogram.com/courses&quot;&gt;Execute Program - SQL&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zerotomastery.io/courses/sql-bootcamp/&quot;&gt;ZTM - SQL Bootcamp&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sqlzoo.net/wiki/SQL_Tutorial&quot;&gt;SQL Zoo Practices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deeper&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Botros &amp;amp; Tinley - High Performance MySQL&lt;/li&gt;
  &lt;li&gt;Build a DB from scratch&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;core-tools&quot;&gt;Core tools&lt;/h3&gt;

&lt;p&gt;Git&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://gitimmersion.com/&quot;&gt;Git Immersion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=RGOj5yH7evk&quot;&gt;Freecodecamp - Beginner Git&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Uszj_k0DGsg&quot;&gt;Freecodecamp - Intermediate Git&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=qsTthZi23VE&quot;&gt;Freecodecamp - Advanced Git&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://git-scm.com/doc&quot;&gt;Git Reference Manual&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Terminal&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://learncodethehardway.org/unix/&quot;&gt;Zed Shaw - Learn Unix The Hard Way&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.oreilly.com/library/view/learning-the-bash/0596009658/&quot;&gt;Cameron Newham - Learning The Bash Shell&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.freecodecamp.org/news/command-line-for-beginners/&quot;&gt;Freecodecamp - Command Line For Beginners&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zerotomastery.io/courses/learn-bash-scripting/&quot;&gt;ZTM - Bash Scripting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Text Editor&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://learn.vscode.one/&quot;&gt;Master VScode&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://danielmiessler.com/p/vim/&quot;&gt;Daniele Meissler - Learn Vim For the Last Time&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.executeprogram.com/courses/regexes&quot;&gt;Execute Program - Regular Expressions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browser dev tools&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=gTVpBbFWry8&quot;&gt;Freecodecamp - Chrome DevTools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developer experience tools&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Offline documentation browser:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://devdocs.io/&quot;&gt;Devdocs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://kapeli.com/dash&quot;&gt;Dash for macOS&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;API development: &lt;a href=&quot;https://www.usebruno.com/&quot;&gt;Bruno&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Database GUI: &lt;a href=&quot;https://tableplus.com/&quot;&gt;Table plus&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;General productivity: &lt;a href=&quot;https://www.raycast.com/&quot;&gt;Raycast&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;details&gt;
    &lt;summary&gt;According to the Pragmatic Programmer book, aim to do the following actions using only the keyboard with your text editor of choice&lt;/summary&gt;
    &lt;li&gt;Edit text by selecting by character, word, line, paragraph&lt;/li&gt;
    &lt;li&gt;Move selected character, word, line, and paragraph&lt;/li&gt;
    &lt;li&gt;Find exact/partial matched word, pattern, delimiters, function, etc&lt;/li&gt;
    &lt;li&gt;Indent and reindent block of code&lt;/li&gt;
    &lt;li&gt;Comment and uncomment blocks of code&lt;/li&gt;
    &lt;li&gt;Undo and redo changes&lt;/li&gt;
    &lt;li&gt;Split the editor window into multiple rows or columns, and jump between them&lt;/li&gt;
    &lt;li&gt;Go to a specific line number&lt;/li&gt;
    &lt;li&gt;Sort selected lines by descending and ascending&lt;/li&gt;
    &lt;li&gt;Create multiple cursors to select and edit the text in parallel.&lt;/li&gt;
    &lt;li&gt;Open new terminal and problem windows in the current project.&lt;/li&gt;
    &lt;li&gt;Start service and run all/specific test cases in project&lt;/li&gt;
&lt;/details&gt;

&lt;h2 id=&quot;fundamentals-of-software-craftsmanship&quot;&gt;Fundamentals of software craftsmanship&lt;/h2&gt;

&lt;h3 id=&quot;general-craft&quot;&gt;General craft&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/&quot;&gt;David Thomas &amp;amp; Andrew Hunt - The Pragmatic Programmer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.oreilly.com/library/view/code-complete-2nd/0735619670/&quot;&gt;Steve McConnell - Code Complete&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;object-oriented-programming&quot;&gt;Object Oriented Programming&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.poodr.com/&quot;&gt;Sandi Metz - Practical Object Oriented Design In Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://avdi.codes/moom/&quot;&gt;Avdi Grimm - Mastering The Object-Oriented Mindset In Ruby And Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Rebecca Wirfs-Brock, Wilkerson, Wiener - Designing Object-Oriented Software (also see this PDF)&lt;/li&gt;
  &lt;li&gt;Matt Weisfeld, The Object-Oriented Thought Process&lt;/li&gt;
  &lt;li&gt;Freeman and Pryce - Growing Object-Oriented Software, Guided by Tests (GOOS) #goos-bookclub&lt;/li&gt;
  &lt;li&gt;Eric Evans - Domain Driven Design&lt;/li&gt;
  &lt;li&gt;Vaughn Vernon - Implementing Domain Driven Design&lt;/li&gt;
  &lt;li&gt;David West - Object Thinking&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;design-and-software-architecture&quot;&gt;Design and software architecture&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://cleancoders.com/series/clean-code&quot;&gt;Robert Martin - Clean Code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Robert Martin - Clean Architecture&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.goodreads.com/en/book/show/2278064&quot;&gt;Russ Olsen - Design Patterns In Ruby&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Gang of Four - Design Patterns&lt;/li&gt;
  &lt;li&gt;Freeman, Baters, Sierra - Head First Design Patterns&lt;/li&gt;
  &lt;li&gt;Martin Fowler - Domain Driven Design&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/&quot;&gt;Martin Kleppmann - Designing Data-Intensive Applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://understandingdistributed.systems/&quot;&gt;Roberto Vitillo - Understanding Distributed Systems&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://architecturethehardparts.com/&quot;&gt;Ford, Richards, Sadalage, Dehghani - Software Architecture: The Hard Parts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.oreilly.com/library/view/clean-architecture-a/9780134494272/&quot;&gt;Robert C. Martin - Clean Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;refactoring&quot;&gt;Refactoring&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.oreilly.com/library/view/refactoring-improving-the/9780134757681/&quot;&gt;Martin Fowler - Refactoring&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Jay Fields - Refactoring Ruby&lt;/li&gt;
  &lt;li&gt;Joshua Kerievsky - Refactoring To Patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;testing&quot;&gt;Testing&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://books.thoughtbot.com/assets/testing-rails.pdf&quot;&gt;Thoutbot: Testing Rails&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gorails.com/series/testing-ruby-on-rails&quot;&gt;GoRails: Testing Series&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Micheal Feathers - Working Effectively With Existing Code&lt;/li&gt;
  &lt;li&gt;Gerard Meszaros - XUnit Test Patterns: Refactoring Test Code&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;security&quot;&gt;Security&lt;/h3&gt;

&lt;p&gt;Intro&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://websecurity-academy.com/&quot;&gt;Web Security Academy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zerotomastery.io/courses/learn-ethical-hacking/&quot;&gt;ZTM - Ethical Hacking Bootcamp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deeper&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Lewandowski, Adkins, Beyer, et al - Building Secure and Reliable Systems&lt;/li&gt;
  &lt;li&gt;Gilam &amp;amp; Barth - Zero Trust Networks&lt;/li&gt;
  &lt;li&gt;Cliff Stoll - The Cuckoo’s Egg: Tracking a Spy Through the Maze of Computer Espionage&lt;/li&gt;
  &lt;li&gt;Michael Zalewski - Tangled Web: A Guide to Securing Modern Web Applications&lt;/li&gt;
  &lt;li&gt;Yaworski - Real-World Bug Hunting&lt;/li&gt;
  &lt;li&gt;Stuttard &amp;amp; Pinto - The Web Application Hacker’s Handbook&lt;/li&gt;
  &lt;li&gt;Sandworm: A New Era of Cyberwar and the Hunt for the Kremlin’s Most Dangerous Hackers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;performance&quot;&gt;Performance&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.railsspeed.com/&quot;&gt;Nate Berkopec - Rails Performance&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.speedshop.co/2015/07/29/scaling-ruby-apps-to-1000-rpm.html&quot;&gt;Nate Berkopec - Scaling Rails to 1000 RPM&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;devops&quot;&gt;DevOps&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Site Reliability Engineering: How Google Runs Production Systems&lt;/li&gt;
  &lt;li&gt;Murphy, Rensin, Kawahara, Throne, Beyer - The Site Reliability Workbook: Practical Ways to Implement SRE&lt;/li&gt;
  &lt;li&gt;Brendan Gregg - Systems Performance: Enterprise and the Cloud&lt;/li&gt;
  &lt;li&gt;Stevens &amp;amp; Rago - Advanced Programming in Unix Environment&lt;/li&gt;
  &lt;li&gt;Kim, Debois, Willis, Humber -  The DevOps Handbook&lt;/li&gt;
  &lt;li&gt;Michael Nygard - Release It!: Design and Deploy Production-Ready Software&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;fundamentals-of-computer-science&quot;&gt;Fundamentals of computer science&lt;/h2&gt;

&lt;p&gt;This is the lifelong journey of learning the &lt;a href=&quot;https://medium.com/bradfield-cs/cutting-through-to-what-matters-48baf397806f&quot;&gt;computer science foundations&lt;/a&gt; that will stand the test of time.&lt;/p&gt;

&lt;h3 id=&quot;resources-1&quot;&gt;Resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://csprimer.com/&quot;&gt;CS Primer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://teachyourselfcs.com/&quot;&gt;Teachyourselfcs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://bradfieldcs.com/&quot;&gt;Bradfield School of CS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.recurse.com/&quot;&gt;Recurse Center&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;low-level-programming&quot;&gt;Low-level programming&lt;/h3&gt;

&lt;p&gt;Recommendations from co-workers on low-level programming resources.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.amazon.ca/Low-Level-Programming-Assembly-Execution-Architecture/dp/1484224027&quot;&gt;Igor Zhirkovlow - Low-level programming&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://interpreterbook.com/&quot;&gt;Thorsten Ball - Writing An Interpreter In Go&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://compilerbook.com/&quot;&gt;Thorsten Ball - Writing A Compiler In Go (Book)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.zero2prod.com/&quot;&gt;Zero To Production With Rust&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stevedonovan.github.io/rust-gentle-intro/&quot;&gt;A Gentle Introduction To Rust&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;healthy-reminders-and-inspiration&quot;&gt;Healthy reminders and inspiration&lt;/h2&gt;

&lt;p&gt;Peak under the magic&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Start to peek underneath the “magic”&lt;/li&gt;
  &lt;li&gt;Re-build the tools, read the source code instead of the docs, and contribute
to the open source project&lt;/li&gt;
  &lt;li&gt;Look for courses that teach how to build the tools from scratch in addition to
courses that teach how to use them&lt;/li&gt;
  &lt;li&gt;Play around with the source code and see what breaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no rush&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4vjNAQYHCnQ&quot;&gt;It’s a marathon, not a sprint&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Software development is a craft, not an academic study&lt;/li&gt;
  &lt;li&gt;The only way to get better is to learn by doing, building, and getting
  feedback on your work&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4vjNAQYHCnQ&quot;&gt;No one can learn everything there is to know in
software&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=UAzQZdttdsA&quot;&gt;Don’t try to memorize things&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;It’s okay to take weeks to months-long breaks from learning if it’s becoming
too much or the season of life is too full&lt;/li&gt;
  &lt;li&gt;Make sure to protect the fun&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The place of books&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Books are collections of learnings that authors have gained over time by actually
doing things and making the mistakes&lt;/li&gt;
  &lt;li&gt;Books are not a primary way of learning craft-based skill sets&lt;/li&gt;
  &lt;li&gt;Books are there to refine a craft using knowledge, mistakes, and learnings
from those that have gone before&lt;/li&gt;
  &lt;li&gt;You do not learn to ride a bike by reading about it&lt;/li&gt;
  &lt;li&gt;Improve the consumption of books by stopping just before the author implements
the solution and first &lt;strong&gt;really&lt;/strong&gt; trying to implement it yourself. Then compare
to see how the author did it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The place of courses&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Courses are also not the primary way of learning craft-based skill sets&lt;/li&gt;
  &lt;li&gt;Courses are there to get you started or introduce a new concept or tool&lt;/li&gt;
  &lt;li&gt;Can improve the consumption of course by building along with the instructor&lt;/li&gt;
  &lt;li&gt;The goal is that after the course you then build independently&lt;/li&gt;
  &lt;li&gt;Improve the consumption of courses by stopping just before the instructor
implements the solution and first &lt;strong&gt;really&lt;/strong&gt; trying to implement it yourself.
Then compare to see how the author did it&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Defining A Good Software Developer</title>
   <link href="https://emmanueletti.com/2023/04/06/defining-a-good-software-developer"/>
   <updated>2023-04-06T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/06/defining-a-good-software-developer</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#software-development-as-house-building&quot;&gt;Software development as house building&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#having-a-product-mindset&quot;&gt;Having a product mindset&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#solving-problems-not-writing-code&quot;&gt;Solving problems, not writing code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#making-good-software&quot;&gt;Making good software&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#flexibility-easy-to-change&quot;&gt;Flexibility (easy to change)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#simplicity&quot;&gt;Simplicity&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#understandability-easy-to-reason-about&quot;&gt;Understandability (easy to reason about)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#reliability&quot;&gt;Reliability&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#maintainability&quot;&gt;Maintainability&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#scalability&quot;&gt;Scalability&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#working-with-other-humans&quot;&gt;Working with other humans&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#attitude&quot;&gt;Attitude&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#communication&quot;&gt;Communication&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#productivity&quot;&gt;Productivity&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pitfalls&quot;&gt;Pitfalls&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#trying-to-memorize-everything-learn-everything-then-burning-out&quot;&gt;Trying to memorize everything, learn everything, then burning out&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#chasing-the-shiny-new-and-popular&quot;&gt;Chasing the shiny, new, and popular&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#not-thinking-in-terms-of-tradeoffs&quot;&gt;Not thinking in terms of tradeoffs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#blindly-following-best-practice-without-understanding-the-why&quot;&gt;Blindly following “best practice” (without understanding the why)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#rushing-to-ship&quot;&gt;Rushing to ship&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;“You did not learn to ride a bike by reading about it. You learnt by jumping
on a bike and falling a lot. Over time you figured out how to stay upright and
steer. In the same way, you can only truely learn to become a better
programmer by writing a lot of code. In the beginining that code will be bad.
You will make a lot of mistakes. But then you will learn from all those
efforts. Books are just a collection of the hard lessons authors have learnt
over thier careers as working engineers.”&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;– Senior Engineer @ Shopify&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;software-development-as-house-building&quot;&gt;Software development as house building&lt;/h2&gt;

&lt;p&gt;A house is meant to solve a real
problem for someone. It provides shelter from the elements, storage for
belongings and supplies, and grows with the changing needs of the occupants.&lt;/p&gt;

&lt;p&gt;Houses are more than a combination of a roof and four walls. There are other
concerns such as electricity, plumbing, heating, insulation, aesthetics, and
more. Every decision made when building the house, from the design to the
materials chosen, comes with tradeoffs.&lt;/p&gt;

&lt;p&gt;Any contractor worth their invoice can build a house. What separates a good
contractor from a bad one, is the considerations and care taken in the craft of
house building.&lt;/p&gt;

&lt;p&gt;Imagine two beautiful homes built by two different contractors. House A is built
by Jane, an experienced contractor who’s learned some important lessons
throughout her career. House B is built by Joe, a contractor who does not yet
have the same level of experience as Jane.&lt;/p&gt;

&lt;p&gt;At first glance, both houses look amazing. But when the occupants of Joe’s house
move in, they find that some details have been missed and some cupboards are
misaligned - okay not so bad they think.&lt;/p&gt;

&lt;p&gt;After a few weeks, they find that the plumbing stops working at random times of
the day. Kind of annoying. After a few months, they decide to install a new hot
water heater. But the schematics that Joe left them are difficult to make sense
of. The owner decides to ignore the schematics and look at the pipes directly to
trace how they’ve been put together. But the implementation is such a black box
that Joe needs to be brought back to do the installation himself.&lt;/p&gt;

&lt;p&gt;After a few years, the family of Joe’s house have had new family members move in -
their needs have changed. They would like to renovate part of the house to
accommodate their new situation. Having learned their lesson, they decide to
hire Jane to oversee the renovations and expansion. She tells them that,
unfortunately, the structural layout of the house and the placement of key
electrical and heating components are so fixed that making the changes will
require an entire rebuild of the house.&lt;/p&gt;

&lt;p&gt;Even though both Jane and Joe accomplished the fundamental goal of a contractor
(building a house that meets the needs of the occupants), Joe’s house was not:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Flexible (easy to change)&lt;/li&gt;
  &lt;li&gt;Reliable&lt;/li&gt;
  &lt;li&gt;Maintainable&lt;/li&gt;
  &lt;li&gt;Understandable (easy to reason about)&lt;/li&gt;
  &lt;li&gt;Scalable with growing the needs of the occupants&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;having-a-product-mindset&quot;&gt;Having a product mindset&lt;/h2&gt;

&lt;p&gt;The first and most important goal of a good software developer is to remember
that the business value of their role is to provide solutions to business
problems. This is where both Jane and Joe accomplished their main goals.&lt;/p&gt;

&lt;p&gt;Does their work contribute to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Reducing the time and financial cost of operations&lt;/li&gt;
  &lt;li&gt;Increasing product quality&lt;/li&gt;
  &lt;li&gt;Increasing the customer base&lt;/li&gt;
  &lt;li&gt;Increasing the number of products to sell&lt;/li&gt;
  &lt;li&gt;Innovating and creating new product categories to sell&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is in opposition to seeing software development value &lt;em&gt;solely&lt;/em&gt; as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Implementing the most cutting-edge technology&lt;/li&gt;
  &lt;li&gt;Constantly shipping product features (many features do not make a good product)&lt;/li&gt;
  &lt;li&gt;Accumulating technical expertise (this will naturally happen over time)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;solving-problems-not-writing-code&quot;&gt;Solving problems, not writing code&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Although it may sound surprising, the primary focus of a software developers
job is not writing code but rather creating value through the use of software
that was written. Code is simply a tool to achieve this end goal. Code -&amp;gt;
Software -&amp;gt; Value.&lt;/p&gt;

  &lt;p&gt;What you write needs to fill some need in the world — some tool that users
will use, some automation that reduces costs, something people will pay for
(with their time, money, or attention). We can simplify it. If you build
something with shitty technologies that provides great value to the users —
you’ve served your purpose as a software developer. If you’ve built something
with great technology that offers shitty value to the user — you didn’t.&lt;/p&gt;

  &lt;p&gt;Elegant code, best practices, smart solutions, design patterns — these are
done for the sake of your fellow software engineers who will work on the
codebase after you rather than helping you fulfill the purpose of bringing
value. (Mind you, bringing value can also mean building a scalable solution
that doesn’t crash, which requires the code to be at least somewhat decent.)&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;– &lt;a href=&quot;https://vadimkravcenko.com/shorts/things-they-didnt-teach-you/&quot;&gt;Vamid
Kravcenko&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;making-good-software&quot;&gt;Making good software&lt;/h2&gt;

&lt;p&gt;Making good software is an art versus a science. It’s learned over time and with
experience. Many of the lessons learned will be through painful and expensive
mistakes, and that is okay.&lt;/p&gt;

&lt;h3 id=&quot;security&quot;&gt;Security&lt;/h3&gt;

&lt;p&gt;One of the fastest ways to lose customer confidence is through a security
breach. People trust companies with their private data and engineers owe it to them
to do everything possible to learn and optimize for security. Rely on the simple
and battle-tested solutions over the fancy and brittle.&lt;/p&gt;

&lt;h3 id=&quot;flexibility-easy-to-change&quot;&gt;Flexibility (easy to change)&lt;/h3&gt;

&lt;p&gt;The only constant in software is that things will change. Business requirements
will change, the team with learn more about the domain, new features will need
to be added, etc.&lt;/p&gt;

&lt;p&gt;All the considerations of patterns and best practices are about making software
easy to change. Software systems that are tightly coupled, not well tested,
complex, and hard to understand are painful to change. The goal is not to
optimize for the computer but to optimize for the humans who will make changes
to the software.&lt;/p&gt;

&lt;h3 id=&quot;simplicity&quot;&gt;Simplicity&lt;/h3&gt;

&lt;p&gt;Build simple solutions. Avoid clever tricks, “elegant” one-liners, or using the
newest trendy tools. Simple solutions, with no more moving pieces that are
needed, are much easier to maintain by a wider variety of people and skill sets.&lt;/p&gt;

&lt;p&gt;Sometimes software developers can even achieve the primary goal of finding
solutions to business problems without writing any code at all.&lt;/p&gt;

&lt;h3 id=&quot;understandability-easy-to-reason-about&quot;&gt;Understandability (easy to reason about)&lt;/h3&gt;

&lt;p&gt;Don’t build black boxes.&lt;/p&gt;

&lt;p&gt;When an event happens in the system, team members should be able to logically
piece together what happened and communicate exactly why it happened. Anyone
looking at the architecture diagram or logic flow should be able to make sense
of how it’s put together.&lt;/p&gt;

&lt;p&gt;Black boxes can look like convoluted methods and functions, confusing
components, poor documentation, and overly complex system architectures. Just
like the simplicity principle, &lt;em&gt;strive&lt;/em&gt; to make solutions easy to hold in your
brain.&lt;/p&gt;

&lt;p&gt;Understandability can be improved with a mindset of building for the next person
to maintain. When building, imagine yourself having to dive into the software a
year later to fix a time-sensitive bug.&lt;/p&gt;

&lt;h3 id=&quot;reliability&quot;&gt;Reliability&lt;/h3&gt;

&lt;p&gt;Reliability is all about how often your system breaks, how easily your system
can break, how your system handles itself when things go wrong, minimizing data
loss and business interruptions when systems break, and the practices around
getting the system back online and building back better.&lt;/p&gt;

&lt;h3 id=&quot;maintainability&quot;&gt;Maintainability&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;“If something blows up, we need to have made it possible and easy for the correct state
of the system to be recoverable, either by the system itself or by those
operating the system”&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;– Senior Engineer @ Shopify&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good software should &lt;em&gt;strive&lt;/em&gt; to be easy to maintain. Writing easy-to-read code,
building simple solutions, avoiding “clever tricks”, keeping updated
documentation, good git commit practices, and writing good tests should help
with making a system easy to maintain.&lt;/p&gt;

&lt;h3 id=&quot;scalability&quot;&gt;Scalability&lt;/h3&gt;

&lt;p&gt;Scalable software grows and shrinks to meet the demands of the business. But be
careful with premature and untargeted optimizations. These are the root of all evil.&lt;/p&gt;

&lt;h2 id=&quot;working-with-other-humans&quot;&gt;Working with other humans&lt;/h2&gt;

&lt;h3 id=&quot;attitude&quot;&gt;Attitude&lt;/h3&gt;

&lt;p&gt;Be kind. Be humble. Be curious. Ask LOTS of questions. Fight against FOLD (Fear
Of Looking Dumb). Treat others as you would want to be treated.&lt;/p&gt;

&lt;h3 id=&quot;communication&quot;&gt;Communication&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;⚠️ Work in progress&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;productivity&quot;&gt;Productivity&lt;/h3&gt;

&lt;p&gt;Focus on &lt;a href=&quot;https://www.youtube.com/watch?v=c3pzcV9yi24&quot;&gt;one needle-moving task&lt;/a&gt;
per day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.goodreads.com/en/book/show/25744928&quot;&gt;Deep Work&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://maketime.blog/&quot;&gt;Make Time Framework&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;pitfalls&quot;&gt;Pitfalls&lt;/h2&gt;

&lt;h3 id=&quot;trying-to-memorize-everything-learn-everything-then-burning-out&quot;&gt;Trying to memorize everything, learn everything, then burning out&lt;/h3&gt;

&lt;p&gt;The value of a software developer is not measured by how much technical knowledge
a person has accumulated. Technical knowledge comes, goes, and accumulates as a
person navigates a career and the different projects they are exposed to.&lt;/p&gt;

&lt;p&gt;Software developers are professional problem solvers that use computational tools
and engineering craft to do needle-moving amounts of “work” for other people.
This is done via a systematic way of identifying, breaking down, and clarifying
problems to their smallest components. Then researching potential solutions to
the problems, while exploring trade-offs. And then (the final 20% of the time)
implementing the solutions.&lt;/p&gt;

&lt;p&gt;Pick a core set of tools, and master them. When researching other solutions, it’s
important to timebox the process to keep from rabbit trailing and going deeper
into the technology than the problem warrants.&lt;/p&gt;

&lt;p&gt;Instead of trying to learn everything at once, focus on knowing enough to solve
the problems in front of you. Trust that when you need to solve a problem, you
will be well-equipped to learn what’s necessary to solve it (Just In Time
learning).&lt;/p&gt;

&lt;p&gt;Follow your curiosity and spend extra time outside of work projects learning new things.
Focus on understanding the “shape” of the thing. Some questions to ask while
exploring a new technology or topic:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What is it?&lt;/li&gt;
  &lt;li&gt;How does it work under the hood?&lt;/li&gt;
  &lt;li&gt;What is the historical context around this thing?&lt;/li&gt;
  &lt;li&gt;What problem is it meant to solve?&lt;/li&gt;
  &lt;li&gt;What are the alternative ways of solving the same problem?&lt;/li&gt;
  &lt;li&gt;What are its trade-offs?&lt;/li&gt;
  &lt;li&gt;Can I build a prototype with this thing?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;chasing-the-shiny-new-and-popular&quot;&gt;Chasing the shiny, new, and popular&lt;/h3&gt;

&lt;p&gt;Boring is good. A lot of the new and shiny technologies in the industry have been
built to solve extremely niche problems for large tech companies. for 80% of use
cases, the old battle-tested solutions are perfectly fine.&lt;/p&gt;

&lt;p&gt;Many of today’s $10M+ businesses are sitting on “boring” tech stacks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ruby (est. 1996)&lt;/li&gt;
  &lt;li&gt;Monolithic Rails (est. 2004)&lt;/li&gt;
  &lt;li&gt;Postgresql (est. 1986)&lt;/li&gt;
  &lt;li&gt;Redis (est. 2009)&lt;/li&gt;
  &lt;li&gt;Sidekiq (est. 2012)&lt;/li&gt;
  &lt;li&gt;Heroku (est. 2009)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of chasing tutorials for the newest framework, tool, or technology,
focus on mastering the foundational things that have stood the test of time.&lt;/p&gt;

&lt;p&gt;But don’t &lt;em&gt;completely&lt;/em&gt; ignore the new and shiny. As with most of life,
moderation is key and it’s nice to explore out of curiosity.&lt;/p&gt;

&lt;h3 id=&quot;not-thinking-in-terms-of-tradeoffs&quot;&gt;Not thinking in terms of tradeoffs&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Every decision&lt;/strong&gt; has tradeoffs - nothing comes for free. A good practice is
writing RFCs for major decisions to help process the pros and cons of a
decision.&lt;/p&gt;

&lt;h3 id=&quot;blindly-following-best-practice-without-understanding-the-why&quot;&gt;Blindly following “best practice” (without understanding the why)&lt;/h3&gt;

&lt;p&gt;Understand the “why” behind the best practice. This will help with gauging when it’s appropriate
to break the best practice. For example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Blindly following DRY may result in picking the wrong abstraction too early&lt;/li&gt;
  &lt;li&gt;Blindly following YAGNI may keep you from building your software in a way that
anticipates coming changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;rushing-to-ship&quot;&gt;Rushing to ship&lt;/h3&gt;

&lt;p&gt;Rushing to ship can mean putting out software that does not meet the above
considerations of “good quality”.&lt;/p&gt;

&lt;p&gt;Whatever time and money is saved in today’s
shortcuts will be small in comparison to the time and money lost in tomorrow’s
bugs, customer frustrations, and painful feature additions.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The Value of a Software Developer</title>
   <link href="https://emmanueletti.com/2023/04/05/the-value-of-a-software-developer"/>
   <updated>2023-04-05T00:00:00+00:00</updated>
   <id>https://emmanueletti.com/2023/04/05/the-value-of-a-software-developer</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-computer&quot;&gt;The computer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-internet&quot;&gt;The internet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-general-importance-of-these-tools&quot;&gt;The general importance of these tools&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-business-importance-of-these-tools&quot;&gt;The business importance of these tools&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;“So the reason programmers sometimes get paid a lot of money, I think, is
  because we can build systems that leverage computers to do an unreasonable
  amount of work. If you build Gmail’s spam system, you can remove spam from the
  inboxes of millions of people! This is kind of magical and amazing and it’s
  worth all of the bugs and dealing with computers.”&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;– Julia Evans&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An important part of being human is the drive to create. Beautiful things,
destructive things, physical goods, abstract ideas.&lt;/p&gt;

&lt;h2 id=&quot;the-computer&quot;&gt;The computer&lt;/h2&gt;

&lt;p&gt;One incredible thing we have made is the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Computer&quot;&gt;computer&lt;/a&gt;. A computer is a machine that
performs sequences of calculations and logical operations many times faster than
the human brain. Operations can be combined into collections of logic meant to
accomplish specific tasks. These are called &lt;strong&gt;software programs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Over the years, we have built up layers of abstractions to create the modern
computing machines that we use daily. Instead of teletyping binary instructions
into room-sized mainframe machines to perform scientific research calculations;
we click, drag, draw, and type into portable laptops made up of hardware
components and software systems to accomplish general-purpose productivity
tasks.&lt;/p&gt;

&lt;h2 id=&quot;the-internet&quot;&gt;The internet&lt;/h2&gt;

&lt;p&gt;The next major invention came when we linked these computing machines together
to form a network called the Internet. This allowed computers to pass
information between each other across physical fiber optic cables.&lt;/p&gt;

&lt;p&gt;Today a person can write a set of instructions (software) on their
Macbook Pro in a trendy co-working space in Vancouver, BC, and deploy those
instructions through the internet to hundreds of specialized computers in a
Google data center in New York, where they are executed and the results made
available to the rest of the world.&lt;/p&gt;

&lt;h2 id=&quot;the-general-importance-of-these-tools&quot;&gt;The general importance of these tools&lt;/h2&gt;

&lt;p&gt;The reason computers, connected via the internet, have become so important to
society is that they make it easier for us to fulfill that core human drive to
create.&lt;/p&gt;

&lt;p&gt;Computers can help us build tools that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Make life easier for individuals&lt;/li&gt;
  &lt;li&gt;Help businesses operate more efficiently. A network of computers can h&lt;/li&gt;
  &lt;li&gt;Allow us to share information and disperse ideas around the world&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The combination of human creativity, curiosity, and
millions of transistors, has meant that creating things requires a lot less
resources than it used to.&lt;/p&gt;

&lt;h2 id=&quot;the-business-importance-of-these-tools&quot;&gt;The business importance of these tools&lt;/h2&gt;

&lt;p&gt;A business is nothing more than an individual or team solving a problem for a
target customer base. The problems being solved are important enough to the
customer base that they are willing to give money (a societal representation of
value) in exchange for the solutions. A family will pay a monthly subscription
to Netflix because Netflix’s product is solving their problem of boredom.&lt;/p&gt;

&lt;p&gt;If some of these solutions can be turned into systems of logical operations and
calculations (software programs), then they can be performed by computers -
which need no sleep, food, or water. Once created, these software systems can
serve a small niche of hundreds of people or be scaled to meet the needs of
millions of people around the world.&lt;/p&gt;

&lt;p&gt;Even if a business’s primary way of providing solutions to others can’t be
turned into software, many functions within that business can be made a lot
easier with the help of computers. Think of the payroll software that powers
your local garbage disposal company.&lt;/p&gt;

&lt;p&gt;The reason automating a simple payroll process is valuable is because of its effect
on one or more of the main concerns every business has:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Reducing the time and financial costs of its operations&lt;/li&gt;
  &lt;li&gt;Increasing the quality of its products&lt;/li&gt;
  &lt;li&gt;Increasing the number of products it creates&lt;/li&gt;
  &lt;li&gt;Innovating and creating new product categories to sell&lt;/li&gt;
  &lt;li&gt;Increasing the number of customers it serves&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The individuals who can build and maintain these software systems are the
software developers. They work with entrepreneurs (people dedicated to finding
profitable problems to solve) or decision makers within established organizations to
take “business” problems, clarify them, and present solutions made up of
software systems that are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Flexible (easy to change)&lt;/li&gt;
  &lt;li&gt;Reliable&lt;/li&gt;
  &lt;li&gt;Maintainable&lt;/li&gt;
  &lt;li&gt;Understandable (easy to reason about)&lt;/li&gt;
  &lt;li&gt;Scalable&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 

</feed>
