<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shrouk Abozeid</title>
    <description>The latest articles on DEV Community by Shrouk Abozeid (@shroukabozeid).</description>
    <link>https://dev.to/shroukabozeid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4008684%2Fddf07757-4921-49f6-8aa8-bd77aeda61b0.jpg</url>
      <title>DEV Community: Shrouk Abozeid</title>
      <link>https://dev.to/shroukabozeid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shroukabozeid"/>
    <language>en</language>
    <item>
      <title>Learning Go as a Ruby Developer — Part 4: What can we do with a single "for"</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Fri, 07 Aug 2026 16:32:53 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-part-4-what-can-we-do-with-a-single-for-3320</link>
      <guid>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-part-4-what-can-we-do-with-a-single-for-3320</guid>
      <description>&lt;p&gt;So loops in ruby has several ways to implement&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;until&lt;/span&gt; &lt;span class="n"&gt;finished&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go looks at all of this and basically says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We only need one loop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That loop is &lt;code&gt;for&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before getting into loops, though, let's look at conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conditions in Go
&lt;/h2&gt;

&lt;p&gt;Go has the familiar &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;else if&lt;/code&gt;, and &lt;code&gt;else&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Adult"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Minor"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax is pretty close to Ruby, but there is one important difference.&lt;/p&gt;

&lt;p&gt;Go does &lt;strong&gt;not&lt;/strong&gt; use &lt;code&gt;end&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Adult"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Minor"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go uses curly braces to define the block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Adult"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Minor"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Coming from Ruby, I had to get used to seeing &lt;code&gt;{}&lt;/code&gt; everywhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  Boolean Operators
&lt;/h2&gt;

&lt;p&gt;The familiar operators are there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// not active&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// exactly 18&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for inequality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// not 18&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the basic logic isn't particularly difficult to transition to.&lt;/p&gt;

&lt;p&gt;It's mostly the syntax that's different.&lt;/p&gt;

&lt;p&gt;now going back to loops&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;for&lt;/code&gt; Loop
&lt;/h2&gt;

&lt;p&gt;Go has only one looping construct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The traditional form looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialization&lt;/strong&gt; — runs before the first iteration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Condition&lt;/strong&gt; — checked before every iteration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post statement&lt;/strong&gt; — runs after every iteration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is very similar to the traditional C-style loop.&lt;/p&gt;

&lt;p&gt;And this is where my C++ nostalgia started showing up.&lt;/p&gt;

&lt;p&gt;Go doesn't have separate &lt;code&gt;times&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, or &lt;code&gt;until&lt;/code&gt; loops.&lt;/p&gt;

&lt;p&gt;Instead, you use &lt;code&gt;for&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One keyword, several forms.&lt;/p&gt;




&lt;h2&gt;
  
  
  The While-Like &lt;code&gt;for&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;What if we don't need the initialization and post statements?&lt;/p&gt;

&lt;p&gt;No problem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This behaves like a &lt;code&gt;while&lt;/code&gt; loop.&lt;/p&gt;

&lt;p&gt;In other words:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is Go's version of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of those examples where Go's simplicity starts making more sense.&lt;/p&gt;

&lt;p&gt;Instead of introducing another keyword for &lt;code&gt;while&lt;/code&gt;, Go reuses &lt;code&gt;for&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Infinite Loops
&lt;/h2&gt;

&lt;p&gt;You can even remove the condition completely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// keep going&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates an infinite loop.&lt;/p&gt;

&lt;p&gt;Of course, you'll usually want some way to escape it.&lt;/p&gt;

&lt;p&gt;That's where &lt;code&gt;break&lt;/code&gt; comes in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The loop keeps running until the &lt;code&gt;break&lt;/code&gt; statement is reached.&lt;/p&gt;

&lt;p&gt;Ruby has a similar concept:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;

  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, Go doesn't need a separate &lt;code&gt;loop&lt;/code&gt; construct.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;for&lt;/code&gt; handles it.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;break&lt;/code&gt; and &lt;code&gt;continue&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Go also provides the familiar &lt;code&gt;break&lt;/code&gt; and &lt;code&gt;continue&lt;/code&gt; keywords.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;break&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;break&lt;/code&gt; exits the loop completely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The loop stops when &lt;code&gt;i&lt;/code&gt; reaches &lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;continue&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;continue&lt;/code&gt; skips the remaining code in the current iteration and moves to the next one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This skips even numbers and prints the odd ones.&lt;/p&gt;

&lt;p&gt;Ruby has the same concepts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;even?&lt;/span&gt;

  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ruby uses &lt;code&gt;next&lt;/code&gt; where Go uses &lt;code&gt;continue&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;range&lt;/code&gt;: The Go Way to Iterate Over Collections
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;for&lt;/code&gt; loop becomes even more interesting when combined with &lt;code&gt;range&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;range&lt;/code&gt; form allows you to iterate over collections such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;arrays&lt;/li&gt;
&lt;li&gt;slices&lt;/li&gt;
&lt;li&gt;strings&lt;/li&gt;
&lt;li&gt;maps&lt;/li&gt;
&lt;li&gt;channels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Charlie"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us both the index and the value.&lt;/p&gt;

&lt;p&gt;The output would look conceptually like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 Alice
1 Bob
2 Charlie
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Comparing &lt;code&gt;range&lt;/code&gt; with Ruby
&lt;/h3&gt;

&lt;p&gt;In Ruby, I'd probably write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Charlie"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, if I don't need the index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Go, &lt;code&gt;range&lt;/code&gt; handles both cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if I only care about the value, I can ignore the index:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;_&lt;/code&gt; tells Go that I intentionally don't need that value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switch Statements
&lt;/h2&gt;

&lt;p&gt;Go also has &lt;code&gt;switch&lt;/code&gt; for conditional logic.&lt;/p&gt;

&lt;p&gt;A simple switch looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Moneypenny"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Miss Moneypenny"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Bond"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Bond, James Bond"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Q"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This is Q"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike Ruby's &lt;code&gt;case&lt;/code&gt;, Go doesn't require an &lt;code&gt;end&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s2"&gt;"Moneypenny"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Miss Moneypenny"&lt;/span&gt;
&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s2"&gt;"Bond"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Bond, James Bond"&lt;/span&gt;
&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s2"&gt;"Q"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"This is Q"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Unknown"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is another interesting form of Go's &lt;code&gt;switch&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Switch Without an Expression
&lt;/h2&gt;

&lt;p&gt;You can leave the value out completely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Minor"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Adult"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;case&lt;/code&gt; is essentially a condition.&lt;/p&gt;

&lt;p&gt;This can be useful when you have several related conditions.&lt;/p&gt;

&lt;p&gt;Ruby's &lt;code&gt;case&lt;/code&gt; can also be used for conditional expressions, although the syntax and matching behavior are different.&lt;/p&gt;




&lt;h2&gt;
  
  
  Multiple Values in a Case
&lt;/h2&gt;

&lt;p&gt;A Go case can match multiple values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"Moneypenny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Bond"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Dr No"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Secret agent"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unknown"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means we don't need separate cases for every value when they should produce the same result.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;fallthrough&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;One thing that caught my attention was &lt;code&gt;fallthrough&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Normally, once a Go &lt;code&gt;switch&lt;/code&gt; finds a matching case, it stops.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"second"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only the first case runs.&lt;/p&gt;

&lt;p&gt;If you explicitly use &lt;code&gt;fallthrough&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fallthrough&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"second"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"third"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first and second cases run, but the third does not.&lt;/p&gt;

&lt;p&gt;This is different from the behavior many people might expect from C-style switch statements, where falling through can happen unless you explicitly stop it.&lt;/p&gt;

&lt;p&gt;Go makes the behavior explicit with &lt;code&gt;fallthrough&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go vs Ruby: Control Flow
&lt;/h2&gt;

&lt;p&gt;Here's how the two languages compare.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;Ruby&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Condition&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;if&lt;/code&gt; / &lt;code&gt;else&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;if&lt;/code&gt; / &lt;code&gt;else&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not&lt;/td&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Equality&lt;/td&gt;
&lt;td&gt;&lt;code&gt;==&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;==&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inequality&lt;/td&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Main loop&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Multiple constructs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;While loop&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for condition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;while condition&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infinite loop&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;loop do&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iterate collection&lt;/td&gt;
&lt;td&gt;&lt;code&gt;for ... range&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.each&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skip iteration&lt;/td&gt;
&lt;td&gt;&lt;code&gt;continue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;next&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exit loop&lt;/td&gt;
&lt;td&gt;&lt;code&gt;break&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;break&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;&lt;code&gt;switch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;case&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple switch values&lt;/td&gt;
&lt;td&gt;&lt;code&gt;case "a", "b"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;when "a", "b"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Neither approach is necessarily better.&lt;/p&gt;

&lt;p&gt;They're just optimizing for different things.&lt;/p&gt;

</description>
      <category>go</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Design Patterns in Ruby #5: Abstract Factory Pattern</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Wed, 05 Aug 2026 16:02:00 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/design-patterns-in-ruby-5-abstract-factory-pattern-4ioa</link>
      <guid>https://dev.to/shroukabozeid/design-patterns-in-ruby-5-abstract-factory-pattern-4ioa</guid>
      <description>&lt;p&gt;In the previous article, we explored the &lt;strong&gt;Factory Method&lt;/strong&gt; pattern and saw how it delegates object creation to subclasses.&lt;/p&gt;

&lt;p&gt;But what if your application doesn't need to create just &lt;strong&gt;one object&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;What if it needs an entire &lt;strong&gt;family of related objects&lt;/strong&gt; that are designed to work together?&lt;/p&gt;

&lt;p&gt;That's exactly the problem the &lt;strong&gt;Abstract Factory&lt;/strong&gt; pattern solves.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Imagine you're building an e-commerce application that supports multiple payment providers.&lt;/p&gt;

&lt;p&gt;Your application currently integrates with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stripe&lt;/li&gt;
&lt;li&gt;PayPal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each payment provider, you need several related objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Payment processor&lt;/li&gt;
&lt;li&gt;A Refund processor&lt;/li&gt;
&lt;li&gt;A Customer service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Stripe, those objects might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StripePayment
StripeRefund
StripeCustomer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For PayPal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PayPalPayment
PayPalRefund
PayPalCustomer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you instantiate each object manually, your code quickly becomes filled with conditionals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:stripe&lt;/span&gt;
  &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;StripePayment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;refund&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;StripeRefund&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;StripeCustomer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PayPalPayment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;refund&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PayPalRefund&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PayPalCustomer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem isn't creating a single object anymore.&lt;/p&gt;

&lt;p&gt;It's ensuring that &lt;strong&gt;all related objects come from the same payment provider&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The client shouldn't accidentally create a &lt;code&gt;StripePayment&lt;/code&gt; with a &lt;code&gt;PayPalRefund&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Abstract Factory
&lt;/h2&gt;

&lt;p&gt;The Gang of Four defines Abstract Factory as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Provide an interface for creating families of related or dependent objects without specifying their concrete classes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of asking for individual objects, the client asks a factory to provide an entire family.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StripeFactory
 ├── Payment
 ├── Refund
 └── Customer

PayPalFactory
 ├── Payment
 ├── Refund
 └── Customer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client never knows which concrete classes it's using.&lt;/p&gt;

&lt;p&gt;It only communicates with the factory interface.&lt;/p&gt;




&lt;h2&gt;
  
  
  Structure
&lt;/h2&gt;

&lt;p&gt;The pattern consists of five participants.&lt;/p&gt;

&lt;h3&gt;
  
  
  Abstract Factory
&lt;/h3&gt;

&lt;p&gt;Defines the interface for creating every product in the family.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;create_payment&lt;/span&gt;
&lt;span class="n"&gt;create_refund&lt;/span&gt;
&lt;span class="n"&gt;create_customer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Concrete Factory
&lt;/h3&gt;

&lt;p&gt;Implements the Abstract Factory.&lt;/p&gt;

&lt;p&gt;Each concrete factory creates one complete product family.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;StripeFactory&lt;/li&gt;
&lt;li&gt;PayPalFactory&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Abstract Product
&lt;/h3&gt;

&lt;p&gt;Defines the common interface shared by each product.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Payment&lt;/li&gt;
&lt;li&gt;Refund&lt;/li&gt;
&lt;li&gt;Customer&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Concrete Products
&lt;/h3&gt;

&lt;p&gt;The concrete implementations belonging to a specific family.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StripePayment
StripeRefund
StripeCustomer

PayPalPayment
PayPalRefund
PayPalCustomer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Client
&lt;/h3&gt;

&lt;p&gt;The client depends only on the Abstract Factory.&lt;/p&gt;

&lt;p&gt;At runtime, it receives whichever concrete factory is needed.&lt;/p&gt;

&lt;p&gt;This completely decouples the client from concrete implementations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Ruby Example
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Products
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripePayment&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Charging $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; with Stripe"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripeRefund&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Refunding &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; through Stripe"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripeCustomer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Creating Stripe customer: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Charging $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; with PayPal"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalRefund&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Refunding &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; through PayPal"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalCustomer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Creating PayPal customer: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Abstract Factory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentProviderFactory&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_payment&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotImplementedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_refund&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotImplementedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_customer&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotImplementedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Concrete Factories
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StripeFactory&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PaymentProviderFactory&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_payment&lt;/span&gt;
    &lt;span class="no"&gt;StripePayment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_refund&lt;/span&gt;
    &lt;span class="no"&gt;StripeRefund&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_customer&lt;/span&gt;
    &lt;span class="no"&gt;StripeCustomer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalFactory&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PaymentProviderFactory&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_payment&lt;/span&gt;
    &lt;span class="no"&gt;PayPalPayment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_refund&lt;/span&gt;
    &lt;span class="no"&gt;PayPalRefund&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_customer&lt;/span&gt;
    &lt;span class="no"&gt;PayPalCustomer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Client
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CheckoutService&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_customer&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_payment&lt;/span&gt;

    &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;refund&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_refund&lt;/span&gt;
    &lt;span class="n"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transaction_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;StripeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;CheckoutService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"txn_123"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switching to PayPal requires changing only one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PayPalFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;CheckoutService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of the application remains unchanged.&lt;/p&gt;

&lt;p&gt;Notice that &lt;code&gt;CheckoutService&lt;/code&gt; never references &lt;code&gt;StripePayment&lt;/code&gt;, &lt;code&gt;PayPalPayment&lt;/code&gt;, or any other concrete implementation.&lt;/p&gt;

&lt;p&gt;It only communicates with the Abstract Factory.&lt;/p&gt;




&lt;h2&gt;
  
  
  Factory Method vs Abstract Factory
&lt;/h2&gt;

&lt;p&gt;Although both patterns deal with object creation, they solve different problems.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Factory Method&lt;/th&gt;
&lt;th&gt;Abstract Factory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Creates one product&lt;/td&gt;
&lt;td&gt;Creates a family of related products&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uses inheritance&lt;/td&gt;
&lt;td&gt;Uses object composition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subclasses decide what to create&lt;/td&gt;
&lt;td&gt;A factory object decides which family to create&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best when object creation varies&lt;/td&gt;
&lt;td&gt;Best when entire product families vary&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Another way to think about it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Factory Method&lt;/strong&gt; asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which object should I create?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Abstract Factory&lt;/strong&gt; asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which family of objects should I create?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Adding New Products vs New Families
&lt;/h2&gt;

&lt;p&gt;Suppose our payment providers now support &lt;strong&gt;webhooks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We need another product:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;create_webhook&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Abstract Factory, the abstract factory interface must change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentProviderFactory&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_payment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_refund&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_customer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_webhook&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every concrete factory (&lt;code&gt;StripeFactory&lt;/code&gt;, &lt;code&gt;PayPalFactory&lt;/code&gt;, etc.) must also implement &lt;code&gt;create_webhook&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, if you add a completely new payment provider—say &lt;strong&gt;Adyen&lt;/strong&gt;—you simply introduce a new concrete factory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AdyenFactory
 ├── AdyenPayment
 ├── AdyenRefund
 ├── AdyenCustomer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The existing factories remain unchanged.&lt;/p&gt;

&lt;p&gt;That's why people often say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Factory Method is open to new creators.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstract Factory is open to new product families.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Where You'll See It in Rails
&lt;/h2&gt;

&lt;p&gt;Although Rails doesn't explicitly label it as the Abstract Factory pattern, the idea appears in several places.&lt;/p&gt;

&lt;h3&gt;
  
  
  Active Storage
&lt;/h3&gt;

&lt;p&gt;Depending on your configuration, Rails creates a family of storage-related objects for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local Disk&lt;/li&gt;
&lt;li&gt;Amazon S3&lt;/li&gt;
&lt;li&gt;Google Cloud Storage&lt;/li&gt;
&lt;li&gt;Azure Blob Storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your application interacts with a common interface while Rails supplies the correct implementation behind the scenes.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should You Use It?
&lt;/h2&gt;

&lt;p&gt;Use Abstract Factory when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your application works with multiple product families.&lt;/li&gt;
&lt;li&gt;Objects within a family should always be used together.&lt;/li&gt;
&lt;li&gt;You want to switch implementations through configuration.&lt;/li&gt;
&lt;li&gt;You want to isolate your application from concrete classes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid it when you only need to create a single object. In that case, &lt;strong&gt;Factory Method&lt;/strong&gt; or even a &lt;strong&gt;Simple Factory&lt;/strong&gt; is usually a better fit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Factory Method&lt;/strong&gt; pattern creates &lt;strong&gt;one object&lt;/strong&gt; and relies on &lt;strong&gt;inheritance&lt;/strong&gt; to determine which concrete product to instantiate.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Abstract Factory&lt;/strong&gt; pattern creates &lt;strong&gt;families of related objects&lt;/strong&gt; and relies on &lt;strong&gt;composition&lt;/strong&gt; to swap entire implementations at runtime.&lt;/p&gt;

&lt;p&gt;A simple rule to remember is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Factory Method answers:&lt;/strong&gt; &lt;em&gt;Which object should I create?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstract Factory answers:&lt;/strong&gt; &lt;em&gt;Which family of objects should I create?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;for a full example in ruby check this &lt;a href="https://github.com/ShroukAbozeid/design-pattern/tree/main/factory/abstract_factory" rel="noopener noreferrer"&gt;https://github.com/ShroukAbozeid/design-pattern/tree/main/factory/abstract_factory&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Design Patterns in Ruby #4: Simple Factory vs Factory Method</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Tue, 04 Aug 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/design-patterns-in-ruby-4-simple-factory-vs-factory-method-4oml</link>
      <guid>https://dev.to/shroukabozeid/design-patterns-in-ruby-4-simple-factory-vs-factory-method-4oml</guid>
      <description>&lt;p&gt;When building applications, creating an object is rarely as simple as calling &lt;code&gt;User.new&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Different objects may require different initialization logic, validation, external API calls, or configuration. If every class is responsible for deciding &lt;strong&gt;what&lt;/strong&gt; object to create, this logic quickly becomes scattered throughout the codebase.&lt;/p&gt;

&lt;p&gt;Factory patterns solve this problem by separating &lt;strong&gt;object creation&lt;/strong&gt; from &lt;strong&gt;object usage&lt;/strong&gt;, making the code easier to maintain and extend.&lt;/p&gt;

&lt;p&gt;Let's look at the two most common approaches: &lt;strong&gt;Simple Factory&lt;/strong&gt; and &lt;strong&gt;Factory Method&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Factory
&lt;/h2&gt;

&lt;p&gt;it is not actually a design pattern by the book but it is commonly used.&lt;/p&gt;

&lt;p&gt;it has a very basic idea of encapsulating the objects creation from it’s usage&lt;/p&gt;

&lt;p&gt;it has a class ‘Simple Factory’ that contains the logic of creating objects , that factory is used in a “client”  to create the objects then use it &lt;/p&gt;

&lt;p&gt;Instead of allowing clients to instantiate objects directly, a single factory class becomes responsible for deciding which object should be created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;p&gt;A Simple Factory consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;factory class&lt;/strong&gt; that contains all the object creation logic.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;single factory method&lt;/strong&gt; that returns different objects based on some condition.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;client&lt;/strong&gt; that uses the factory instead of creating objects directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;a naive implementation of simple factory in ruby&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserSimpleFactory&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;
      &lt;span class="no"&gt;Admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'customer'&lt;/span&gt;
      &lt;span class="no"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'guest'&lt;/span&gt;
      &lt;span class="no"&gt;Guest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;country: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:country&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
   &lt;span class="k"&gt;else&lt;/span&gt;
     &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'INVALID_TYPE'&lt;/span&gt;
   &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegisterHandler&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;UserSimpleFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:type&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="s2"&gt;"Hello &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Centralizes object creation.&lt;/li&gt;
&lt;li&gt;Keeps clients from depending on concrete classes.&lt;/li&gt;
&lt;li&gt;Easy to understand and implement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;This works well while you only have a few product types.&lt;/p&gt;

&lt;p&gt;However, every time a new user type is introduced, the factory needs another &lt;code&gt;when&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;Eventually the factory becomes a large conditional statement responsible for creating every possible object.&lt;/p&gt;

&lt;p&gt;This violates the &lt;strong&gt;Open/Closed Principle&lt;/strong&gt; because adding a new product requires modifying an existing class.&lt;/p&gt;

&lt;p&gt;at that time you might think to extract parts of this method into different classes and voilà you get a factory method pattern&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzd98cxqmjrdlj8i7amvl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzd98cxqmjrdlj8i7amvl.gif" alt="iron man viola" width="480" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Factory Method
&lt;/h2&gt;

&lt;p&gt;The Gang of Four defines Factory Method as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Define an interface for creating an object, but let subclasses decide which class to instantiate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;this pattern lets a class defer instantiation to subclass. and encapsulates the instantation of concrete types&lt;/p&gt;

&lt;p&gt;The parent class defines the workflow, while each subclass decides which concrete object should be created.&lt;/p&gt;

&lt;p&gt;This removes the need for long &lt;code&gt;case&lt;/code&gt; statements and replaces them with &lt;strong&gt;polymorphism&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Abstract creator : it gives you an interface with method(THE factory method) to create object(product), any other method on this class operates on the object returned by the factory method&lt;/li&gt;
&lt;li&gt;Concrete creator : is a subclass that implement the factory method&lt;/li&gt;
&lt;li&gt;Abstract product; interface(parent) of all products that different concrete creators return&lt;/li&gt;
&lt;li&gt;Concrete product must implement the same interface so that the factories can refere to the interface not the concrete classes &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;this pattern decouples the implementation of the product from its use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegisterHandler&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotImplementedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="s2"&gt;"Hello &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdminRegister&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;RegisterHandler&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerRegister&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;RegisterHandler&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GuestRegister&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;RegisterHandler&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Guest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;country: &lt;/span&gt;&lt;span class="n"&gt;user_args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:country&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the &lt;code&gt;register&lt;/code&gt; method is implemented only once.&lt;/p&gt;

&lt;p&gt;The only thing subclasses customize is &lt;strong&gt;how the user is created&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The registration workflow remains unchanged regardless of the user type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Eliminates large conditional statements.&lt;/li&gt;
&lt;li&gt;Follows the Open/Closed Principle.&lt;/li&gt;
&lt;li&gt;Makes it easy to introduce new product types.&lt;/li&gt;
&lt;li&gt;Uses polymorphism instead of branching logic.&lt;/li&gt;
&lt;li&gt;Keeps creation logic isolated inside dedicated creator classes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off is that it introduces more classes, which can feel unnecessary for small applications.&lt;/p&gt;




&lt;h3&gt;
  
  
  Did you know that Rails framework is full of Factory patterns? 👀
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Example: Action Mailer
&lt;/h4&gt;

&lt;p&gt;Every mailer inherits from &lt;code&gt;ApplicationMailer&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When you define&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMailer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationMailer&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The framework handles the workflow of building and delivering an email.&lt;/p&gt;

&lt;p&gt;Your subclass supplies the message-specific details.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example: Active Job adapters
&lt;/h4&gt;

&lt;p&gt;You write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendEmailJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queue_adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:solid_queue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queue_adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:sidekiq&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each adapter creates its own queue implementation.&lt;/p&gt;

&lt;p&gt;Rails defines the workflow.&lt;/p&gt;

&lt;p&gt;The adapter subclasses provide the implementation&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Simple Factory&lt;/strong&gt; centralizes object creation using conditional logic. It's a pragmatic solution for smaller applications but becomes harder to maintain as the number of products grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Factory Method&lt;/strong&gt; takes a different approach by replacing those conditionals with polymorphism. Instead of modifying one factory every time a new product is added, you create a new creator class that knows how to build that product.&lt;/p&gt;

&lt;p&gt;A good rule of thumb is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If your factory keeps getting longer every time you introduce a new product, it's probably time to replace it with Factory Method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;for a full example in ruby check this &lt;a href="https://github.com/ShroukAbozeid/design-pattern/tree/main/factory" rel="noopener noreferrer"&gt;https://github.com/ShroukAbozeid/design-pattern/tree/main/factory&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>designpatterns</category>
      <category>oop</category>
    </item>
    <item>
      <title>Snehal Ahire - Rails Under a Microscope: Summarized with AI</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Wed, 29 Jul 2026 13:12:23 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/snehal-ahire-rails-under-a-microscope-summarized-with-ai-4424</link>
      <guid>https://dev.to/shroukabozeid/snehal-ahire-rails-under-a-microscope-summarized-with-ai-4424</guid>
      <description>&lt;p&gt;Sometimes I'm lazy to talk notes myself(which ofcourse is better) but instead of not talking notes at all i let ai summarize what i just watched to make sure i didn't drop anything.&lt;/p&gt;

&lt;p&gt;in this video Snehal Talks about performance problems that developers can face in large scale application and what could be some of the causes.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Jv2N_A1OaHI"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So here is her talk in points :D &lt;/p&gt;

&lt;h2&gt;
  
  
  Rails Performance Challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Performance issues in Rails applications, such as slow listing pages, delayed search queries, and long-running Sidekiq batches, cause significant frustration for both users and developers.&lt;/li&gt;
&lt;li&gt;Persistent performance bottlenecks lead to increased infrastructure costs and delays in feature development, making performance optimization a necessity for application survival.&lt;/li&gt;
&lt;li&gt;While developers may be tempted to rewrite slow Rails applications in languages like Rust or Go, such rewrites are often risky and costly; instead, applications should be analyzed to identify specific bottlenecks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Data Retrieval Optimization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code that appears innocent in the early stages of an application can evolve into a performance bottleneck as the system scales over many years.&lt;/li&gt;
&lt;li&gt;Common performance issues in mature applications include memory bloat, memory leaks, and inefficient database queries.&lt;/li&gt;
&lt;li&gt;Fetching unnecessary data, such as loading all columns when only a few are needed, is inefficient and becomes increasingly problematic as the number of rows grows into the millions.&lt;/li&gt;
&lt;li&gt;Developers should optimize data retrieval by selecting only the specific columns required for the task.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pagination Strategies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Standard pagination using &lt;code&gt;offset&lt;/code&gt; is suitable for small datasets but becomes inefficient for large databases because the system must scan and discard all preceding records to reach the requested page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Keyset pagination&lt;/code&gt; is a more efficient alternative for large datasets because it fetches only the required data without scanning and discarding previous records.&lt;/li&gt;
&lt;li&gt;Keyset pagination is &lt;strong&gt;index-friendly&lt;/strong&gt;, leveraging indexed columns like ID or created_at to provide consistent performance regardless of how deep into the dataset the user navigates.&lt;/li&gt;
&lt;li&gt;Keyset pagination is an &lt;strong&gt;effective strategy for features like "Load More" or infinite scrolls&lt;/strong&gt; because it uses pointers from the last row of a previous page to start the next query, though it prevents direct navigation to specific page numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Query and Caching Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To prevent N+1 queries, Rails 7 and later versions offer &lt;code&gt;strict loading&lt;/code&gt; features that can be used during development to avoid accidental performance issues.&lt;/li&gt;
&lt;li&gt;Caching should only be implemented when the value of recomputing data exceeds the costs associated with cache maintenance and invalidation, as improper caching can negatively impact performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Memory Management and Heap Fragmentation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Memory bloat occurs when there is a significant discrepancy between the actual size of live objects in an application and the Resident Set Size (RSS) reported by the system.&lt;/li&gt;
&lt;li&gt;The Memory Profiler gem is a tool used to diagnose memory issues by identifying memory allocations and retained objects, categorized by gem, location, class, or specific line of code.&lt;/li&gt;
&lt;li&gt;Memory consumption in Ruby is often driven by &lt;code&gt;arrays&lt;/code&gt;, &lt;code&gt;strings&lt;/code&gt;, and &lt;code&gt;hashes&lt;/code&gt;, which are dynamic allocations stored in the heap, while static functions are managed in the stack.&lt;/li&gt;
&lt;li&gt;Ruby manages heap memory by dividing pages into multiple slots; when a new object is created, Ruby searches for a free slot within these pages.&lt;/li&gt;
&lt;li&gt;When a page is full, Ruby requests additional pages from the system allocator—such as &lt;code&gt;Malloc&lt;/code&gt; or &lt;code&gt;Jemalloc&lt;/code&gt;—rather than communicating directly with the operating system.&lt;/li&gt;
&lt;li&gt;Heap fragmentation occurs when the garbage collector frees objects, leaving non-adjacent holes in memory that are too small or poorly positioned to accommodate new object allocations.&lt;/li&gt;
&lt;li&gt;Because Ruby cannot utilize these non-adjacent free slots, it is forced to request more pages from the system allocator, leading to an increase in total memory usage despite the presence of free space.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Allocator and Garbage Collection Dynamics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Allocator fragmentation also occurs when the system allocator cannot merge non-adjacent memory blocks, a problem that can be mitigated in multi-threaded environments like Sidekiq by configuring Malloc Arena Max to two or four.&lt;/li&gt;
&lt;li&gt;Increased numbers of arenas contribute to higher levels of memory fragmentation.&lt;/li&gt;
&lt;li&gt;Locators retain memory and maintain caches of different block sizes to facilitate instant future allocations.&lt;/li&gt;
&lt;li&gt;Garbage collectors do not immediately return memory to the system, instead retaining it for future use, which keeps process memory usage high even when objects are no longer needed.&lt;/li&gt;
&lt;li&gt;Configuring the heap growth factor can help manage fragmentation, as a higher factor results in less fragmentation.&lt;/li&gt;
&lt;li&gt;Ruby 3.2 introduced variable width allocation, which manages slots through size pools rather than statically to reduce memory bloat and fragmentation, though its effectiveness depends on code support.&lt;/li&gt;
&lt;li&gt;Memory bloat is primarily caused by heap fragmentation, allocator fragmentation, allocators reserving extra memory, and the garbage collector holding onto memory.&lt;/li&gt;
&lt;li&gt;Resident Set Size (RSS) refers to the amount of RAM a specific process uses.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Memory Optimization Techniques
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Loading large datasets into an array can be optimized by using batches with configurable batch sizes instead of loading all records at once.&lt;/li&gt;
&lt;li&gt;Converting large datasets to JSON within Ruby consumes significant memory; offloading this process to the database using functions like &lt;code&gt;row_to_json&lt;/code&gt; or &lt;code&gt;json_agg&lt;/code&gt; is more efficient.&lt;/li&gt;
&lt;li&gt;Reading large CSV files should be done line-by-line or using &lt;code&gt;foreach&lt;/code&gt; rather than loading millions of rows into memory at once.&lt;/li&gt;
&lt;li&gt;Creating temporary objects inside loops, such as date objects, leads to excessive memory usage over millions of iterations; these objects should be created once before the loop and reused, ideally using &lt;code&gt;freeze&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;include?&lt;/code&gt; on arrays inside loops creates new arrays in every iteration, which can be avoided by using a &lt;code&gt;Set&lt;/code&gt; for faster retrieval and freezing the collection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bulk Operations and Database Efficiency
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;destroy&lt;/code&gt; method loads all associations into memory, whereas &lt;code&gt;delete_all&lt;/code&gt; performs a single operation without callbacks or associations, though it requires manual handling of child records to avoid orphaned objects.&lt;/li&gt;
&lt;li&gt;Per-record updates can trigger N+1 query issues and high memory usage; bulk operations like &lt;code&gt;upsert&lt;/code&gt;, &lt;code&gt;update_all&lt;/code&gt;, or &lt;code&gt;upsert_all&lt;/code&gt; are more efficient alternatives.&lt;/li&gt;
&lt;li&gt;Inserting rows one by one for associations, such as orders and line items, creates memory overhead when processing multiple rows.&lt;/li&gt;
&lt;li&gt;Bulk queries can be optimized by using &lt;code&gt;insert&lt;/code&gt; or &lt;code&gt;upsert&lt;/code&gt; operations instead of individual queries.&lt;/li&gt;
&lt;li&gt;Memory bloat issues can be addressed by utilizing batches, reusing data, and freezing objects to prevent redundant object creation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Identifying and Resolving Memory Leaks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A gradual, steady increase in memory usage over time often indicates a memory leak, even if restarting the process temporarily resolves the symptoms.&lt;/li&gt;
&lt;li&gt;Symptoms of a memory leak include a steadily growing Resident Set Size (RSS) that does not decrease after Sidekiq jobs, a heap of objects that are never deallocated, and frequent garbage collection (GC) pauses as the system struggles to clean up unreleased objects.&lt;/li&gt;
&lt;li&gt;Unbounded in-memory objects, such as those stored in class or global variables, can cause memory leaks because the garbage collector cannot release them as long as they remain referenced.&lt;/li&gt;
&lt;li&gt;Replacing class or global variables with local methods allows the garbage collector to automatically free memory after the data is used.&lt;/li&gt;
&lt;li&gt;Closures can lead to memory leaks if they capture large objects rather than specific values, as the captured variables are not released.&lt;/li&gt;
&lt;li&gt;Passing only the specific data required, such as a calculated size rather than an entire array, prevents unnecessary memory retention.&lt;/li&gt;
&lt;li&gt;Implementing these memory optimizations resulted in a 42% reduction in memory usage (from 788 MB to 459 MB) and an 80% reduction in the number of objects (from 11 million to 2 million), while performance time improved from 2 minutes to between 10 and 20 seconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Database Query Tuning and Indexing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Database query performance can be analyzed and tuned using the &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; command in PostgreSQL.&lt;/li&gt;
&lt;li&gt;Adding specific conditions to a query can shift the execution plan from a slow parallel sequential scan to a significantly faster index scan, as demonstrated by a reduction in execution time from 2,800 milliseconds to 0.7 milliseconds.&lt;/li&gt;
&lt;li&gt;Partial indexes are effective only when queries include the specific index conditions, and neglecting these details can lead to high execution times.&lt;/li&gt;
&lt;li&gt;Small, neglected features or individual application problems can cause significant performance degradation across an entire system.&lt;/li&gt;
&lt;li&gt;Materialized views in Postgres serve as physical tables that store computed data, offering an alternative to complex joins across multiple tables or the complications of using read replicas.&lt;/li&gt;
&lt;li&gt;Postgres features such as TS vectors combined with GIN indexes allow for efficient searching across multiple columns by creating a vector for direct querying.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scaling and Infrastructure Management
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Sidekiq can be autoscaled using latency-based queuing, which organizes tasks into multiple queues based on their latency requirements.&lt;/li&gt;
&lt;li&gt;Specialized GIN indexes, which support various operators, can be utilized to achieve faster retrieval speeds for JSON columns.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance Culture and Workflow Integration
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Performance optimization should begin with **profiling and measurement **rather than relying on intuition to identify bottlenecks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database capabilities&lt;/strong&gt;, including indexes, aggregations, and bulk operations, should be leveraged for heavy tasks rather than attempting to reinvent these processes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identifying data patterns&lt;/strong&gt; and understanding how data is derived and processed is essential, as even minor inefficiencies accumulate at scale.&lt;/li&gt;
&lt;li&gt;Performance management is a collaborative responsibility that should be shared across the entire team.&lt;/li&gt;
&lt;li&gt;P*&lt;em&gt;erformance should be integrated into the development workflow&lt;/em&gt;* by setting budgets and monitoring metrics throughout the design, build, and shipping phases, rather than treating it as an afterthought.&lt;/li&gt;
&lt;li&gt;Addressing performance issues requires a &lt;strong&gt;continuous, multi-faceted approach&lt;/strong&gt; rather than a one-time fix or a complete rewrite of the application in a different language.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thanks Snehal for an interesting talk and a great presentation, if you know her profile tag her for credits &lt;/p&gt;

</description>
      <category>rails</category>
      <category>performance</category>
    </item>
    <item>
      <title>Learning Go as a Ruby Developer #3: Functions, Methods, and Why Go Doesn't Have Classes</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Mon, 27 Jul 2026 14:59:31 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-3-functions-methods-and-why-go-doesnt-have-classes-pc7</link>
      <guid>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-3-functions-methods-and-why-go-doesnt-have-classes-pc7</guid>
      <description>&lt;p&gt;One of the biggest mindset shifts I've had while learning Go came when I reached functions and methods.&lt;/p&gt;

&lt;p&gt;As a Ruby developer, almost everything revolves around objects. Every piece of behavior belongs to a class, and every function is really just a method attached to an object.&lt;/p&gt;

&lt;p&gt;Go takes a different approach.&lt;/p&gt;

&lt;p&gt;Functions exist independently, and methods are simply functions with a receiver. There are no classes, no inheritance, but still writing object-oriented code.&lt;/p&gt;

&lt;p&gt;Let's see how Go approaches behavior compared to Ruby.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Felt Strange Coming from Ruby
&lt;/h2&gt;

&lt;p&gt;In Ruby, we rarely think about standalone functions because they don't really exist.&lt;/p&gt;

&lt;p&gt;Everything is an object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want behavior?&lt;/p&gt;

&lt;p&gt;Create a class.&lt;/p&gt;

&lt;p&gt;Need reusable logic?&lt;/p&gt;

&lt;p&gt;Another class or a module.&lt;/p&gt;

&lt;p&gt;Go starts from a much simpler place.&lt;/p&gt;

&lt;p&gt;Most behavior begins as just... a function.&lt;/p&gt;




&lt;h2&gt;
  
  
  Functions in Go
&lt;/h2&gt;

&lt;p&gt;Functions are declared using the &lt;code&gt;func&lt;/code&gt; keyword.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax may look unusual at first, especially if you've spent years writing Ruby.&lt;/p&gt;

&lt;p&gt;Instead of writing the return type first, Go places it &lt;strong&gt;after&lt;/strong&gt; the parameter list.&lt;/p&gt;

&lt;p&gt;Calling the function is exactly what you'd expect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Grouping Parameters
&lt;/h2&gt;

&lt;p&gt;Go lets you group parameters that share the same type.&lt;/p&gt;

&lt;p&gt;Instead of writing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a small feature, but it keeps function declarations much cleaner.&lt;/p&gt;




&lt;h2&gt;
  
  
  Returning Multiple Values
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can capture both results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;quotient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Coming from Ruby, this felt familiar because Ruby also supports multiple assignment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;quotient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference is that in Ruby we're really returning an array, while in Go multiple return values are part of the language itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Named Return Values
&lt;/h2&gt;

&lt;p&gt;One feature I wasn't expecting was named return values.&lt;/p&gt;

&lt;p&gt;Instead of writing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the bare &lt;code&gt;return&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;result&lt;/code&gt; was named in the function signature, Go automatically returns it.&lt;/p&gt;

&lt;p&gt;This is called a &lt;strong&gt;naked return&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Anonymous Functions
&lt;/h2&gt;

&lt;p&gt;Go also supports anonymous functions.&lt;/p&gt;

&lt;p&gt;You can assign them to variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;greet&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or execute them immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Running immediately"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reminded me a lot of Ruby blocks and lambdas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;greet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the syntax is different, the concept feels familiar.&lt;/p&gt;




&lt;h2&gt;
  
  
  Variadic Functions
&lt;/h2&gt;

&lt;p&gt;Sometimes you don't know how many arguments a function should accept.&lt;/p&gt;

&lt;p&gt;Go solves this using variadic parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;...&lt;/code&gt; tells Go to collect all arguments into a slice.&lt;/p&gt;

&lt;p&gt;Ruby has something very similar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was one of the easiest concepts for me to understand because the two languages approach it almost the same way.&lt;/p&gt;




&lt;h2&gt;
  
  
  So Where Are the Classes?
&lt;/h2&gt;

&lt;p&gt;This was the question I kept asking while reading through the documentation.&lt;/p&gt;

&lt;p&gt;If Go doesn't have classes...&lt;/p&gt;

&lt;p&gt;Where do methods live?&lt;/p&gt;

&lt;p&gt;The answer surprised me.&lt;/p&gt;

&lt;p&gt;Methods belong to &lt;strong&gt;types&lt;/strong&gt;, not classes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Methods in Go
&lt;/h2&gt;

&lt;p&gt;A method is simply a function with a receiver.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello,"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can call it like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax felt unusual at first.&lt;/p&gt;

&lt;p&gt;Instead of defining the method inside the type like Ruby does, the receiver appears before the method name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;receiver&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;MethodName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Value Receivers
&lt;/h2&gt;

&lt;p&gt;By default, methods receive a copy of the value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changing &lt;code&gt;p.Name&lt;/code&gt; only changes the copy.&lt;/p&gt;

&lt;p&gt;The original object stays exactly the same.&lt;/p&gt;

&lt;p&gt;This is called a &lt;strong&gt;value receiver&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pointer Receivers
&lt;/h2&gt;

&lt;p&gt;If you want to modify the original value, you use a pointer receiver.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now changes affect the original struct.&lt;/p&gt;

&lt;p&gt;This distinction between value and pointer receivers was one of the first places where Go reminded me of C++.&lt;/p&gt;

&lt;p&gt;Ruby developers usually don't think about this because objects are already passed around by reference-like semantics.&lt;/p&gt;

&lt;p&gt;Go asks you to decide whether you're working with a copy or the original value.&lt;/p&gt;




&lt;h2&gt;
  
  
  Side-by-Side Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;Ruby&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standalone functions&lt;/td&gt;
&lt;td&gt;Everything is a method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;func&lt;/code&gt; keyword&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;def&lt;/code&gt; keyword&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple return values&lt;/td&gt;
&lt;td&gt;Usually arrays or multiple assignment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anonymous functions&lt;/td&gt;
&lt;td&gt;Lambdas and Procs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Variadic parameters (&lt;code&gt;...&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Splat operator (&lt;code&gt;*&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Methods attached to types&lt;/td&gt;
&lt;td&gt;Methods defined inside classes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Value receivers&lt;/td&gt;
&lt;td&gt;Objects usually mutated directly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pointer receivers&lt;/td&gt;
&lt;td&gt;Reference-like object semantics&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;p&gt;Ruby's object model is incredibly elegant.&lt;/p&gt;

&lt;p&gt;Everything feels consistent because everything is an object.&lt;/p&gt;

&lt;p&gt;Go takes a more lightweight approach.&lt;/p&gt;

&lt;p&gt;Instead of encouraging you to wrap every behavior inside a class, it asks a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does this really need to belong to a type?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes the answer is yes—a method makes sense.&lt;/p&gt;

&lt;p&gt;Other times, a standalone function is perfectly fine.&lt;/p&gt;

&lt;p&gt;Go is trying to remove the parts it considers unnecessary while keeping the parts that are genuinely useful.&lt;/p&gt;

&lt;p&gt;This has been one of the most interesting lessons so far in my Go journey, what about you?&lt;/p&gt;

</description>
      <category>go</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Learning Go as a Ruby Developer # 2: Variables, Constants, and Why Go Doesn't Trust You</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Sat, 25 Jul 2026 14:20:50 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-2-variables-constants-and-why-go-doesnt-trust-you-49ji</link>
      <guid>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-2-variables-constants-and-why-go-doesnt-trust-you-49ji</guid>
      <description>&lt;p&gt;One of the first differences I noticed when learning Go was how seriously it takes types.&lt;/p&gt;

&lt;p&gt;Coming from Ruby. I rarely think about their types because Ruby figures everything out at runtime.&lt;/p&gt;

&lt;p&gt;Go has a very different philosophy.&lt;/p&gt;

&lt;p&gt;It wants to know exactly what every variable is, and if it doesn't know, it'll ask you to be explicit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Felt Strange Coming from Ruby
&lt;/h2&gt;

&lt;p&gt;In Ruby, creating variables couldn't be easier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Alice"&lt;/span&gt;
&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ruby decides the type at runtime.&lt;/p&gt;

&lt;p&gt;Later I can even do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same variable can hold completely different kinds of objects throughout the program.&lt;/p&gt;

&lt;p&gt;Go doesn't allow that.&lt;/p&gt;

&lt;p&gt;Once a variable has a type, that type is fixed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Declaring Variables in Go
&lt;/h2&gt;

&lt;p&gt;The most explicit way to declare a variable is by specifying its type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Alice"&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is checked during compilation, long before your program ever runs.&lt;/p&gt;

&lt;p&gt;If you later try to assign a different type, the compiler will stop you immediately.&lt;/p&gt;

&lt;p&gt;This felt a bit strict—but it also means many bugs are caught before the program starts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Type Inference
&lt;/h2&gt;

&lt;p&gt;Fortunately, Go doesn't always require you to write the type yourself.&lt;/p&gt;

&lt;p&gt;It can often infer it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go knows this is a &lt;code&gt;bool&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Likewise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes a &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Short Variable Declaration
&lt;/h2&gt;

&lt;p&gt;Inside functions, Go provides an even shorter syntax.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;
&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;:=&lt;/code&gt; operator both declares the variable and lets Go infer its type.&lt;/p&gt;

&lt;p&gt;If you're writing local variables, you'll probably use this style most of the time.&lt;/p&gt;

&lt;p&gt;One thing I learned from my notes is that this syntax &lt;strong&gt;can only be used inside functions&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Declaring Multiple Variables
&lt;/h2&gt;

&lt;p&gt;Go also makes it easy to declare multiple variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or with inferred types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For larger groups, Go encourages this style:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
    &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Constants
&lt;/h2&gt;

&lt;p&gt;Constants are declared using &lt;code&gt;const&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MaxUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also group them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;Pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3.14&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike variables, constants cannot be changed after they're declared.&lt;/p&gt;

&lt;p&gt;Ruby has constants too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;MAX_USERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But every Ruby developer knows the truth...&lt;/p&gt;

&lt;p&gt;Ruby will happily let you change it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;MAX_USERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll get a warning, not an error.&lt;/p&gt;

&lt;p&gt;Go, on the other hand, simply refuses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Zero Values
&lt;/h2&gt;

&lt;p&gt;If you declare a variable without assigning anything, Go automatically initializes it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values become:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Zero Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float64&lt;/td&gt;
&lt;td&gt;0.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;""&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Coming from Ruby, I expected something similar to &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead, Go gives every type a sensible default.&lt;/p&gt;

&lt;p&gt;That design avoids a lot of unnecessary initialization code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Type Conversion
&lt;/h2&gt;

&lt;p&gt;Another thing that immediately stood out was that Go &lt;strong&gt;doesn't automatically convert between types&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Suppose we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;45&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Converting it to a floating-point number requires an explicit conversion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Likewise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;uint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every conversion must be intentional.&lt;/p&gt;

&lt;p&gt;Ruby is much more forgiving.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"45"&lt;/span&gt;

&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in many cases Ruby performs conversions automatically for you.&lt;/p&gt;

&lt;p&gt;Go deliberately avoids this.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating Values with &lt;code&gt;make&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;One line in my notes that initially confused me was this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike arrays in many languages, &lt;code&gt;make&lt;/code&gt; creates and initializes certain built-in data structures.&lt;/p&gt;

&lt;p&gt;In this example, it creates a slice with a length of three.&lt;/p&gt;

&lt;p&gt;I'll dive much deeper into slices later in the series, but for now it's enough to know that &lt;code&gt;make&lt;/code&gt; is commonly used when creating slices, maps, and channels.&lt;/p&gt;




&lt;h2&gt;
  
  
  So to conclude:
&lt;/h2&gt;

&lt;p&gt;Changing a type?&lt;/p&gt;

&lt;p&gt;Be explicit.&lt;/p&gt;

&lt;p&gt;Creating a variable?&lt;/p&gt;

&lt;p&gt;Be explicit—or let the compiler infer it.&lt;/p&gt;

&lt;p&gt;Converting numbers?&lt;/p&gt;

&lt;p&gt;Be explicit.&lt;/p&gt;

&lt;p&gt;At first it felt like the language didn't trust me :D&lt;/p&gt;

&lt;p&gt;Now I think it's more accurate to say Go doesn't trust assumptions.&lt;/p&gt;

&lt;p&gt;Instead of guessing what I meant, it asks me to say exactly what I want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ruby optimizes for flexibility.&lt;br&gt;
Go optimizes for correctness.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>ruby</category>
      <category>rails</category>
      <category>programming</category>
    </item>
    <item>
      <title>Learning Go as a Ruby Developer # 1: How Go Programs Actually Run</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Tue, 14 Jul 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-part-1-understanding-how-go-programs-actually-run-3eh0</link>
      <guid>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-part-1-understanding-how-go-programs-actually-run-3eh0</guid>
      <description>&lt;p&gt;Recently I started learning Go, and one of the first things I noticed was how much it reminded me of C++.&lt;br&gt;
I haven't touched C++ since college, so Go gives me a weird sense of nostalgia :D&lt;/p&gt;

&lt;p&gt;As a Ruby developer, I'm used to writing code and simply executing it.&lt;br&gt;
Go, however, has a much stronger notion of what a program actually is and how it starts running.&lt;/p&gt;

&lt;p&gt;In this article, I want to explore how a Go program is structured and compare it with how we typically think about programs in Ruby&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Felt Strange Coming from Ruby
&lt;/h2&gt;

&lt;p&gt;In Ruby, writing a program is straightforward:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;puts "Hello World"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Save it as &lt;em&gt;hello.rb&lt;/em&gt; and run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby hello.rb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There's no special package declaration, no imports required for basic programs, and no designated entry point function.&lt;/p&gt;

&lt;p&gt;Go takes a very different approach.&lt;/p&gt;

&lt;p&gt;Every executable Go program follows a specific structure, and understanding this structure is one of the first steps to becoming comfortable with the language.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Go Programs Are Structured
&lt;/h2&gt;

&lt;p&gt;A typical Go file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="s"&gt;"fmt"&lt;/span&gt; 
&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are three important pieces here:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Package Declaration
&lt;/h3&gt;

&lt;p&gt;Every Go file begins with a package declaration:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;package main&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Packages are Go's mechanism for organizing code.&lt;/p&gt;

&lt;p&gt;If you want to build an executable application, the package must be named main.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Imports
&lt;/h3&gt;

&lt;p&gt;Go requires explicit imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler will actually complain if you import something you don't use.&lt;/p&gt;

&lt;p&gt;As a Ruby developer, this felt unusual because Ruby happily allows unused &lt;br&gt;
requires:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'csv'&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go prefers keeping dependencies explicit and clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The main Function
&lt;/h3&gt;

&lt;p&gt;Every executable Go program starts execution in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;main&lt;/code&gt;function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accepts no arguments&lt;/li&gt;
&lt;li&gt;returns no values&lt;/li&gt;
&lt;li&gt;acts as the application's entry point&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;code&gt;main()&lt;/code&gt; finishes, the program exits.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Program Execution Works
&lt;/h2&gt;

&lt;p&gt;According to the Go specification, a complete program consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one package named main&lt;/li&gt;
&lt;li&gt;all packages imported by main&lt;/li&gt;
&lt;li&gt;all transitive dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Program execution happens in two stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initialize packages&lt;/li&gt;
&lt;li&gt;Execute main()&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once &lt;code&gt;main()&lt;/code&gt;returns, the program terminates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running vs Building Programs
&lt;/h2&gt;

&lt;p&gt;Go provides two common ways to execute code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run directly
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;go run hello.go&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This compiles and runs the program immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build an executable
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;go build hello.go
./hello
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a standalone binary.&lt;/p&gt;

&lt;p&gt;In Ruby: applications are distributed as source code and interpreted at runtime.&lt;/p&gt;

&lt;p&gt;Coming from Rails, where so much setup happens automatically, Go feels so explicit.&lt;/p&gt;

&lt;p&gt;At the same time, that explicitness means you have to think about things that Ruby usually hides from you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;while Ruby optimizes for developer happiness and speed of iteration, Go forces me to understand what's actually happening.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What about you? do you use Ruby or Go, or both ? and how was the transition for you ?&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Design Patterns in Ruby #3: Decorator Pattern</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Mon, 13 Jul 2026 15:11:23 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/design-patterns-in-ruby-3-decorator-pattern-12an</link>
      <guid>https://dev.to/shroukabozeid/design-patterns-in-ruby-3-decorator-pattern-12an</guid>
      <description>&lt;p&gt;&lt;strong&gt;Inheritance&lt;/strong&gt; is powerful but doesn’t always lead to flexible designs and Decorator Pattern is one of the solutions to balance between inheritance and flexibility &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decorators&lt;/strong&gt; work like object wrappers that add functionality/behavior to the object during run time instead of compile time.&lt;/p&gt;

&lt;p&gt;we said wrapper*&lt;em&gt;S&lt;/em&gt;* with an S because you can wrap as many as your object need, adding layers to your Main object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure of the Decorator Pattern
&lt;/h2&gt;

&lt;p&gt;The Decorator Pattern consists of four main parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Component&lt;/strong&gt; – the main abstraction that can be used directly or wrapped by decorators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete Component&lt;/strong&gt; – the actual object whose behavior we want to extend dynamically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decorator&lt;/strong&gt; – implements the same interface as the component and &lt;strong&gt;has a&lt;/strong&gt; component object that it wraps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete Decorators&lt;/strong&gt; – extend the decorator and add new behavior before or after delegating to the wrapped object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At first, this may sound a bit abstract, so let's look at a practical example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Rack Middleware
&lt;/h2&gt;

&lt;p&gt;If you've worked with Ruby on Rails, you've already used one of the best real-world examples of the Decorator Pattern: &lt;strong&gt;Rack middleware&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each middleware wraps another application object, adds its own behavior, and then delegates the request to the wrapped object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Component&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotImplementedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Concrete Component&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;App&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing request: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Decorator&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Middleware&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;App&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Concrete Decorators&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggingMiddleware&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Middleware&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[LOG] Received request for &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[LOG] Response status: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationMiddleware&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Middleware&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[AUTH] Authenticating user"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:authenticated&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Unauthorized"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimingMiddleware&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Middleware&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[TIMING] Request took &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ms"&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Usage&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;LoggingMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;AuthenticationMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TimingMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="s2"&gt;"/articles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;authenticated: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[AUTH] Authenticating user
[LOG] Received request for /articles
Processing request: /articles
[LOG] Response status: 200
[TIMING] Request took 0.12ms

[200, {}, ["OK"]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Application&lt;/code&gt; is our &lt;strong&gt;Concrete Component&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Middleware&lt;/code&gt; is the &lt;strong&gt;Decorator&lt;/strong&gt; that wraps another component.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LoggingMiddleware&lt;/code&gt;, &lt;code&gt;AuthenticationMiddleware&lt;/code&gt;, and &lt;code&gt;TimingMiddleware&lt;/code&gt; are &lt;strong&gt;Concrete Decorators&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Each middleware adds behavior before, after, or around the original &lt;code&gt;call&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;We can add, remove, or reorder middleware without modifying the original &lt;code&gt;Application&lt;/code&gt; class.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's particularly interesting is that this is almost exactly how Rack itself builds a web application stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MethodOverride&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Session&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each middleware wraps the previous object, creating a chain of decorators that process requests and responses.&lt;/p&gt;

&lt;p&gt;In real Rack applications there isn't a common &lt;code&gt;App&lt;/code&gt; base class because Ruby relies on duck typing. As long as an object responds to &lt;code&gt;call&lt;/code&gt;, it can participate in the middleware stack. &lt;/p&gt;

&lt;p&gt;The example above introduces an explicit &lt;code&gt;App&lt;/code&gt; class only to make the Decorator Pattern structure easier to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Decorators use inheritance mainly for &lt;strong&gt;type compatibility&lt;/strong&gt;, not for behavior reuse.&lt;/li&gt;
&lt;li&gt;New behavior is acquired through &lt;strong&gt;composition&lt;/strong&gt; rather than deep inheritance hierarchies.&lt;/li&gt;
&lt;li&gt;The Decorator Pattern involves a family of decorator classes that wrap concrete components.&lt;/li&gt;
&lt;li&gt;A component can be wrapped by any number of decorators.&lt;/li&gt;
&lt;li&gt;Decorators share the same interface as the objects they decorate.&lt;/li&gt;
&lt;li&gt;The pattern follows the principle of &lt;strong&gt;favoring composition over inheritance&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why favoring composition ?
&lt;/h2&gt;

&lt;p&gt;inheritance becomes difficult to manage when you're trying to mix and match behaviors.&lt;/p&gt;

&lt;p&gt;The number of subclasses grows quickly because every new feature creates more combinations.&lt;/p&gt;

&lt;p&gt;With the Decorator Pattern, each behavior becomes its own object that can be composed dynamically.&lt;/p&gt;

&lt;p&gt;The next time you find yourself creating subclasses for every possible combination of features, it may be worth asking whether a decorator would provide a more flexible solution.&lt;/p&gt;

&lt;p&gt;for a full example in ruby check this &lt;a href="https://github.com/ShroukAbozeid/design-pattern/tree/main/decorator" rel="noopener noreferrer"&gt;https://github.com/ShroukAbozeid/design-pattern/tree/main/decorator&lt;/a&gt; &lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Design Patterns in Ruby #2: Observer Pattern</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Wed, 08 Jul 2026 16:17:55 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/design-patterns-in-ruby-2-observer-pattern-3g2</link>
      <guid>https://dev.to/shroukabozeid/design-patterns-in-ruby-2-observer-pattern-3g2</guid>
      <description>&lt;p&gt;Applications often need to react when something changes.&lt;/p&gt;

&lt;p&gt;When a user signs up, you might want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send a welcome email&lt;/li&gt;
&lt;li&gt;Create a user profile&lt;/li&gt;
&lt;li&gt;Log the activity&lt;/li&gt;
&lt;li&gt;Notify an analytics service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One approach is to put all of this logic inside the signup code. While it works initially, the code quickly becomes difficult to maintain as more responsibilities are added.&lt;/p&gt;

&lt;p&gt;This is exactly the kind of problem the &lt;strong&gt;Observer Pattern&lt;/strong&gt; solves.&lt;/p&gt;

&lt;p&gt;The Observer Pattern is one of the most commonly used &lt;strong&gt;behavioral design patterns&lt;/strong&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It defines a &lt;strong&gt;one-to-many relationship&lt;/strong&gt; between objects so that when one object (the &lt;strong&gt;Subject&lt;/strong&gt;) changes state, all of its dependent objects (the &lt;strong&gt;Observers&lt;/strong&gt;) are notified automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of tightly coupling objects together, the subject simply announces that "something happened," and any interested observers can react.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The pattern consists of two main participants.&lt;/p&gt;

&lt;h4&gt;
  
  
  Subject (Publisher)
&lt;/h4&gt;

&lt;p&gt;The subject owns the state and keeps track of all registered observers.&lt;/p&gt;

&lt;p&gt;Whenever its state changes, it notifies every observer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Observer (Subscriber)
&lt;/h4&gt;

&lt;p&gt;Observers register themselves with the subject.&lt;/p&gt;

&lt;p&gt;When they receive a notification, they perform whatever action they're responsible for.&lt;/p&gt;

&lt;p&gt;A classic real-world example is a UI button.&lt;/p&gt;

&lt;p&gt;The button is the &lt;strong&gt;Subject&lt;/strong&gt;, while event listeners are the &lt;strong&gt;Observers&lt;/strong&gt;. When the button is clicked, every registered listener is notified.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use the Observer Pattern?
&lt;/h2&gt;

&lt;p&gt;Without the Observer Pattern, your code often grows into something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;signup&lt;/span&gt;
    &lt;span class="n"&gt;save&lt;/span&gt;

    &lt;span class="no"&gt;WelcomeMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;track_signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;ActivityLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log_signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every new action requires modifying the &lt;code&gt;signup&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;This makes the class responsible for many unrelated tasks and violates the &lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With the Observer Pattern, the signup process only needs to announce that a user has signed up. Each observer decides how to respond.&lt;/p&gt;




&lt;h2&gt;
  
  
  Loose Coupling
&lt;/h2&gt;

&lt;p&gt;One of the biggest benefits of the Observer Pattern is &lt;strong&gt;loose coupling&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The subject only knows that its observers respond to a common interface (for example, an &lt;code&gt;update&lt;/code&gt; method).&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New observers can be added without changing the subject.&lt;/li&gt;
&lt;li&gt;Observers can be removed at runtime.&lt;/li&gt;
&lt;li&gt;The subject doesn't know or care what each observer does.&lt;/li&gt;
&lt;li&gt;Subjects and observers can evolve independently.&lt;/li&gt;
&lt;li&gt;Each observer has a single, focused responsibility.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Ruby Example
&lt;/h2&gt;

&lt;p&gt;Let's build a simple weather station.&lt;/p&gt;

&lt;p&gt;Whenever the temperature changes, every registered display should update automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherStation&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@observers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@observers&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;observer&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remove_observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@observers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="n"&gt;notify_observers&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;notify_observers&lt;/span&gt;
    &lt;span class="vi"&gt;@observers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@temperature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PhoneDisplay&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Phone Display: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardDisplay&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Dashboard Display: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;station&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WeatherStation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;

&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PhoneDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;DashboardDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phone Display: 25°C
Dashboard Display: 25°C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the temperature changes, the weather station automatically notifies every registered display.&lt;/p&gt;

&lt;p&gt;Notice that &lt;code&gt;WeatherStation&lt;/code&gt; doesn't know anything about phones or dashboards. It only knows that each observer responds to &lt;code&gt;update&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Observer Pattern in Rails
&lt;/h2&gt;

&lt;p&gt;Even if you've never implemented the Observer Pattern yourself, you've probably used it in Rails.&lt;/p&gt;

&lt;p&gt;Some common examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Active Record callbacks (&lt;code&gt;after_create&lt;/code&gt;, &lt;code&gt;after_commit&lt;/code&gt;, &lt;code&gt;before_save&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ActiveSupport::Notifications&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Action Cable broadcasting events to connected clients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;after_create&lt;/span&gt; &lt;span class="ss"&gt;:send_welcome_email&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_welcome_email&lt;/span&gt;
    &lt;span class="no"&gt;WelcomeMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deliver_later&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a &lt;code&gt;User&lt;/code&gt; is created, Rails automatically invokes the callback.&lt;/p&gt;

&lt;p&gt;Although callbacks aren't a textbook implementation of the Observer Pattern, they follow the same fundamental idea: responding automatically when an object's state changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should You Use the Observer Pattern?
&lt;/h2&gt;

&lt;p&gt;The Observer Pattern is a good choice when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple objects need to react to the same event.&lt;/li&gt;
&lt;li&gt;You want to avoid tightly coupling classes together.&lt;/li&gt;
&lt;li&gt;New behaviors should be be added without modifying existing code.&lt;/li&gt;
&lt;li&gt;Different parts of the application should respond independently to state changes.&lt;/li&gt;
&lt;li&gt;You want to follow the &lt;strong&gt;Open/Closed Principle&lt;/strong&gt; and the &lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The Observer Pattern is all about communication without tight coupling.&lt;/p&gt;

&lt;p&gt;Instead of asking every object to perform additional work, the subject simply announces that something has changed.&lt;/p&gt;

&lt;p&gt;Any interested observer can react in its own way.&lt;/p&gt;

&lt;p&gt;In Ruby, where objects communicate through simple interfaces and duck typing, the Observer Pattern is straightforward to implement and can significantly improve the flexibility and maintainability of your applications.&lt;/p&gt;

&lt;p&gt;As your applications grow, you'll find this pattern everywhere—from GUI frameworks to Rails callbacks to event-driven architectures.&lt;/p&gt;

&lt;p&gt;for a full example in ruby check this &lt;a href="https://github.com/ShroukAbozeid/design-pattern/tree/main/observer" rel="noopener noreferrer"&gt;https://github.com/ShroukAbozeid/design-pattern/tree/main/observer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>programming</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Design Patterns in Ruby #1: Strategy Pattern</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Mon, 06 Jul 2026 14:21:52 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/design-patterns-in-ruby-1-strategy-pattern-5h78</link>
      <guid>https://dev.to/shroukabozeid/design-patterns-in-ruby-1-strategy-pattern-5h78</guid>
      <description>&lt;p&gt;When building applications, one of the most common challenges is managing behaviors that can vary over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Behavioral Design Patterns&lt;/strong&gt; helps us design how objects interact with each other in an effective way&lt;br&gt;
One of the most useful behavioral patterns is the &lt;strong&gt;Strategy Pattern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Strategy pattern defines a family of algorithms encapsulate each one and make them interchangeable&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;it provides a way to change the behavior of a class without extending it&lt;/p&gt;

&lt;p&gt;Instead of hardcoding behavior inside a class, the behavior is delegated to a separate object called a &lt;strong&gt;strategy&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Imagine you're building an e-commerce application.&lt;/p&gt;

&lt;p&gt;Customers can pay using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PayPal&lt;/li&gt;
&lt;li&gt;Credit Card&lt;/li&gt;
&lt;li&gt;Bank Transfer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An initial implementation might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Checkout&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:paypal&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing PayPal payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing Credit Card payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:bank_transfer&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing Bank Transfer payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Usage&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:paypal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problems
&lt;/h3&gt;

&lt;p&gt;Every time you add a new payment method:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You modify &lt;code&gt;Checkout&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The class becomes larger&lt;/li&gt;
&lt;li&gt;Testing becomes harder&lt;/li&gt;
&lt;li&gt;You violate the Open/Closed Principle (open for extension, closed for modification)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Applying the Strategy Pattern
&lt;/h2&gt;

&lt;p&gt;Instead of putting all payment logic inside &lt;code&gt;Checkout&lt;/code&gt;, we'll create separate strategy classes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Strategies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentStrategy&lt;/span&gt;
  &lt;span class="c1"&gt;# or make as module and use include instead of &amp;lt;&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotImplementedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PaymentStrategy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing PayPal payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VisaStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PaymentStrategy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing Visa payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankTransferStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PaymentStrategy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing Bank Transfer payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Create the Context
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Context&lt;/strong&gt; is the class that uses a strategy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Checkout&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment_strategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@payment_strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment_strategy&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@payment_strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Use Different Strategies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PayPalStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;VisaStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Runtime Strategy Switching
&lt;/h2&gt;

&lt;p&gt;You can even change strategies while the application is running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PayPalStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;payment_strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;BankTransferStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When Should You Use the Strategy Pattern?
&lt;/h2&gt;

&lt;p&gt;The Strategy Pattern is a good choice when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have multiple implementations of the same behavior.&lt;/li&gt;
&lt;li&gt;You find yourself writing large case or if/else statements.&lt;/li&gt;
&lt;li&gt;You want to follow the Open/Closed Principle.&lt;/li&gt;
&lt;li&gt;You need to switch behavior dynamically at runtime.&lt;/li&gt;
&lt;li&gt;You want to isolate and test algorithms independently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Ruby, where objects are lightweight and composition is encouraged, the Strategy Pattern often feels natural and can significantly improve the design of your applications.&lt;/p&gt;

&lt;p&gt;for a full example in ruby check this &lt;a href="https://github.com/ShroukAbozeid/design-pattern/tree/main/strategy" rel="noopener noreferrer"&gt;https://github.com/ShroukAbozeid/design-pattern/tree/main/strategy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>ruby</category>
      <category>rails</category>
      <category>oop</category>
    </item>
    <item>
      <title>Understanding Rack #2 : Notes from Rebuilding Rails by Noah Gibbs</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Thu, 02 Jul 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/understanding-rack-2-notes-from-rebuilding-rails-by-noah-gibbs-1p2b</link>
      <guid>https://dev.to/shroukabozeid/understanding-rack-2-notes-from-rebuilding-rails-by-noah-gibbs-1p2b</guid>
      <description>&lt;p&gt;A Rack application is typically configured through a &lt;code&gt;config.ru&lt;/code&gt; (RackUp) file. This file defines the stack of middleware that will handle incoming requests before they reach the application itself.&lt;/p&gt;

&lt;p&gt;One of Rack's core ideas is that applications are built from multiple layers. Each layer, called middleware, can inspect, modify, or respond to a request before passing it to the next layer in the stack.&lt;/p&gt;

&lt;p&gt;When Rack builds the middleware stack, it passes each middleware instance the next layer through its &lt;code&gt;initialize&lt;/code&gt; method. The last layer in the chain is the actual application.&lt;/p&gt;

&lt;p&gt;Here's a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config.ru&lt;/span&gt;
&lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Basic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"secret"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="nb"&gt;proc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"text/html"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;use&lt;/code&gt; keyword tells Rack which middleware class to instantiate and what arguments to pass to its constructor. &lt;br&gt;
The &lt;code&gt;run&lt;/code&gt; keyword specifies the final application that will handle the request.&lt;/p&gt;

&lt;p&gt;Rack includes several built-in middleware components, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Rack::Auth::Basic&lt;/code&gt; — HTTP Basic Authentication&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Rack::ContentType&lt;/code&gt; — Automatically sets the response content type&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Rack::ShowExceptions&lt;/code&gt; — Displays a helpful error page when an exception occurs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also many third-party middleware libraries available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Rack::GoogleAnalytics&lt;/code&gt; — Injects Google Analytics tracking code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Rack::Throttle&lt;/code&gt; — Adds request rate limiting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Warden&lt;/code&gt; — A flexible authentication framework used by libraries such as Devise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of Rack's strengths is that you can easily create your own custom middleware and insert it into the stack, allowing you to add application-specific behavior in a clean and reusable way.&lt;/p&gt;

&lt;p&gt;Since Rails is built on top of Rack, every Rails application includes a &lt;code&gt;config.ru&lt;/code&gt; file and uses Rack middleware internally.&lt;/p&gt;

&lt;p&gt;For a deeper look at how Rails integrates with Rack, see the "&lt;a href="https://guides.rubyonrails.org/rails_on_rack.html" rel="noopener noreferrer"&gt;Rails on Rack&lt;/a&gt;" guide in the Rails documentation.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>backend</category>
      <category>rack</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Understanding Rack #1 : Notes from Rebuilding Rails by Noah Gibbs</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Tue, 30 Jun 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/understanding-rack-1-notes-from-rebuilding-rails-by-noah-gibbs-ma8</link>
      <guid>https://dev.to/shroukabozeid/understanding-rack-1-notes-from-rebuilding-rails-by-noah-gibbs-ma8</guid>
      <description>&lt;h3&gt;
  
  
  What is Rack?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Rack&lt;/strong&gt; is a Ruby gem that acts as a &lt;strong&gt;middleman&lt;/strong&gt; between your Ruby framework (like Rails or Sinatra) and the web server/application server that runs your code.&lt;/p&gt;

&lt;p&gt;Think of it like a translator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser &amp;lt;--&amp;gt; Web Server/App Server &amp;lt;--&amp;gt; Rack &amp;lt;--&amp;gt; Rails App
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a browser sends a request:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The server receives it.&lt;/li&gt;
&lt;li&gt;Rack converts the request into a format Rails understands.&lt;/li&gt;
&lt;li&gt;Rails processes the request and generates a response.&lt;/li&gt;
&lt;li&gt;Rack converts the response back into a format the server can send to the browser.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  What is an application server?
&lt;/h3&gt;

&lt;p&gt;An application server is a program that actually &lt;strong&gt;runs your Ruby application&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Puma&lt;/li&gt;
&lt;li&gt;Thin&lt;/li&gt;
&lt;li&gt;Passenger&lt;/li&gt;
&lt;li&gt;WEBrick&lt;/li&gt;
&lt;li&gt;Unicorn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These servers execute your Rails code and return the result to users.&lt;/p&gt;




&lt;h3&gt;
  
  
  Development vs Production
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Development (your local machine)
&lt;/h3&gt;

&lt;p&gt;Usually you run only one application server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rails starts Puma by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser &amp;lt;--&amp;gt; Puma &amp;lt;--&amp;gt; Rails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is simple and works well for development.&lt;/p&gt;




&lt;h3&gt;
  
  
  Production (real website)
&lt;/h3&gt;

&lt;p&gt;In production, there is often a dedicated web server in front of the application server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser &amp;lt;--&amp;gt; Nginx/Apache &amp;lt;--&amp;gt; Puma &amp;lt;--&amp;gt; Rails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nginx/Apache can serve static files efficiently.&lt;/li&gt;
&lt;li&gt;They can handle SSL/HTTPS.&lt;/li&gt;
&lt;li&gt;They can distribute traffic to multiple Puma processes.&lt;/li&gt;
&lt;li&gt;They provide better performance and security.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Real-world analogy
&lt;/h3&gt;

&lt;p&gt;Imagine a restaurant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser&lt;/strong&gt; = customer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx/Apache&lt;/strong&gt; = receptionist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rack&lt;/strong&gt; = waiter translating orders&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rails app&lt;/strong&gt; = chef&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puma&lt;/strong&gt; = kitchen where the chef works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The customer doesn't talk directly to the chef. The request passes through several layers, and Rack helps them communicate using a common language.&lt;/p&gt;

&lt;h3&gt;
  
  
  So in one sentence we can say
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Rack is the standard interface that allows Ruby web servers (Puma, Unicorn, etc.) and Ruby web frameworks (Rails, Sinatra, etc.) to communicate with each other.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>ruby</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
