<?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: Chakrit Wichian</title>
    <description>The latest articles on DEV Community by Chakrit Wichian (@chakrit).</description>
    <link>https://dev.to/chakrit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F260628%2Ff59e1a45-8cbf-4a48-9e45-83481ef4ed44.jpeg</url>
      <title>DEV Community: Chakrit Wichian</title>
      <link>https://dev.to/chakrit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chakrit"/>
    <language>en</language>
    <item>
      <title>If/Else Pyramids</title>
      <dc:creator>Chakrit Wichian</dc:creator>
      <pubDate>Wed, 17 Mar 2021 17:48:32 +0000</pubDate>
      <link>https://dev.to/chakrit/if-else-pyramids-hp2</link>
      <guid>https://dev.to/chakrit/if-else-pyramids-hp2</guid>
      <description>&lt;p&gt;When writing complex method or important "core logic" code paths. We often need to add many branching and condition switches. If we are not careful, we can end up with a "pyramid" built on indentation upon indentation due to the need to add conditional branches over and over during the liftime of the code as new business logic are discovered and handled.&lt;/p&gt;

&lt;p&gt;Often, however, the method usually do have a central "happy path" that does the most meaningful and important work. We can focus on highlight this "happy path" to keep the method obvious as to its purpose and remains highly readable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&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;Payment&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:method&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:card_number&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:wallet_address&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:paid&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;paid&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;Luhn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&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;card_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid CC number'&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="no"&gt;CreditCard&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="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;elsif&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:bitcoin&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;BTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_address&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;wallet_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid BTC wallet address'&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="no"&gt;BTC&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="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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are several strategy we can "streamline" the code path, making the gist of the method, which is to process payments, obvious. The first of which is to inverts the &lt;code&gt;if/else&lt;/code&gt; statement and deal with failure condition early.&lt;/p&gt;

&lt;p&gt;Notice the outermost &lt;code&gt;if !paid&lt;/code&gt; block. This block covers the entirety of the method. This means that the simple "is this payment paid?" check adds to the rest of the method 1 extra level of indentation that does not serve a lot of purpose and keeps the "happy path" 1 level away from the method main scanline.&lt;/p&gt;

&lt;p&gt;The first and simplest fix to improve the readability, is simply:&lt;/p&gt;

&lt;h4&gt;
  
  
  Instead of
&lt;/h4&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;process&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;paid&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;Luhn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&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;card_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid CC number'&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="no"&gt;CreditCard&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="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;elsif&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:bitcoin&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;BTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_address&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;wallet_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid BTC wallet address'&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="no"&gt;BTC&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="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;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;h4&gt;
  
  
  Do this
&lt;/h4&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;process&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;paid&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;Luhn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&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;card_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid CC number'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;CreditCard&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="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;elsif&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:bitcoin&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;BTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_address&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;wallet_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid BTC wallet address'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;BTC&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="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;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;When reading normal text in a book, we expect lines to line up. Deviating from the norm sends a signal to the reader that something is different, or off, about the code.&lt;/p&gt;

&lt;p&gt;However, by wrapping the entire method in an &lt;code&gt;if/else&lt;/code&gt; block we make the entire content of the method reads a little bit harder just for the sake of this one particular condition check which is not the primary purpose of the method at all.&lt;/p&gt;

&lt;p&gt;Inverting the condition so that we can check the &lt;code&gt;paid&lt;/code&gt; condition and exit early leaves the rest of the method at 1-indentation, like any other regular method.&lt;/p&gt;

&lt;p&gt;This improves readability, for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It allows reader to "discard" the paid condition from their mind early when reading
the method. Allowing more cognitive space when debugging.&lt;/li&gt;
&lt;li&gt;It highlights the gist of the method, which should be about processing the payment, not
the noises from conditional checks.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Not?
&lt;/h2&gt;

&lt;p&gt;Most of time, we can take this simple technique and re-apply it all the way until we're left with almost no indentation at all:&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;process&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;paid&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'bad CC number'&lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;Luhn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&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;card_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'bad BTC wallet'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:bitcoin&lt;/span&gt;     &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;BTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_address&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;wallet_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;
    &lt;span class="no"&gt;CreditCard&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="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:bitcoin&lt;/span&gt;
    &lt;span class="no"&gt;BTC&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="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;Now it is very obvious that the method is about delegating the procesing of payments to the right processor class (&lt;code&gt;CreditCard&lt;/code&gt; for credit cards and &lt;code&gt;BTC&lt;/code&gt; for bitcoins.)&lt;/p&gt;

&lt;p&gt;However, experienced coder will notice that we're also muddying the validation of each processor as a cost of doing this as well. Processing credit cards now requires scanning through the &lt;code&gt;.process&lt;/code&gt; method for the second line (doing the &lt;a href="https://en.wikipedia.org/wiki/Luhn_algorithm"&gt;luhn check&lt;/a&gt;) and then skip to the method check to see that the actual processing is done in another class.&lt;/p&gt;

&lt;p&gt;Additionally we have also modified the code flow. The validation checks are now performed separately from the processing block. If we are not careful during real production code edits, &lt;strong&gt;we may introduce subtle bugs due to the changed code paths&lt;/strong&gt; and other developers who need to work on this piece of code may not realize that there is a code pattern to be followed here (validate before processing).&lt;/p&gt;

&lt;h2&gt;
  
  
  Split Condition
&lt;/h2&gt;

&lt;p&gt;Alternatively, another strategy we can use to deal with conditional pyramids is to separate the actual processing out of the conditional branching.&lt;/p&gt;

&lt;h4&gt;
  
  
  Instead of
&lt;/h4&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;process&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;paid&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;Luhn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&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;card_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid CC number'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;CreditCard&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="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;elsif&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:bitcoin&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;BTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_address&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;wallet_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid BTC wallet address'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="no"&gt;BTC&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="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;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Do this
&lt;/h4&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;process&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;paid&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;
    &lt;span class="n"&gt;process_credit_card&lt;/span&gt;
  &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:bitcoin&lt;/span&gt;
    &lt;span class="n"&gt;process_bitcoin&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;def&lt;/span&gt; &lt;span class="nf"&gt;process_credit_card&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid CC number'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;Luhn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check&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;card_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;CreditCard&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="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;def&lt;/span&gt; &lt;span class="nf"&gt;process_bitcoin&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s1"&gt;'invalid BTC wallet address'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;BTC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_address&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;wallet_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;BTC&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="nb"&gt;self&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;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;Sometimes complex condition checking cannot be avoided. Or the refactoring cost in terms of developer time and code complexity may not be worth pursuing. You might also be working with one of those kinds of engineers that &lt;a href="https://medium.com/swlh/stop-using-if-else-statements-f4d2323e6e4"&gt;never writes if-else if they can help it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this case we can still address the complexity directly by splitting the conditional "checking" part from the actual "processing" so that the reader can do all the conditional tree walking to the finish and "unloads" them from their minds before they start looking at the gist of the actual processing.&lt;/p&gt;

&lt;p&gt;Think of this like being a detective. You have to interview several different suspects and find the true culprit. However, there's an extra problem: the road to each of the suspect's houses are very snaky and full of potholes.  Imagine you have a clone of yourself yourself, one of you does the driving while the other think about the case.  This way, it's a lot more likely to figure out the case.&lt;/p&gt;

&lt;p&gt;This accomplishes two more things additional to the first two:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The "switching" of methods are now clear and obvious. The method do not immediately process anything but simply branch to the right processing function.&lt;/li&gt;
&lt;li&gt;We minimized the distractions of branching when we look at individual processing methods (&lt;code&gt;.process_credit_card&lt;/code&gt; don't talk about bitcoins, &lt;code&gt;.process_bitcoin&lt;/code&gt; don't talk about credit cards.) so that each method's processing code are streamlined and more obvious.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now if another developer is tasked with fixing some issue with credit card processing he can quickly zero-in onto the actual processing code and see everything related to it in one place and can quickly tune-out everything else.&lt;/p&gt;

</description>
      <category>style</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Comparing Boolean Expression to True</title>
      <dc:creator>Chakrit Wichian</dc:creator>
      <pubDate>Wed, 17 Mar 2021 17:47:19 +0000</pubDate>
      <link>https://dev.to/prodigy9/comparing-boolean-expression-to-true-357d</link>
      <guid>https://dev.to/prodigy9/comparing-boolean-expression-to-true-357d</guid>
      <description>&lt;p&gt;This has to be the oldest trick in the book in the sense that only really early beginner make these mistakes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Instead of
&lt;/h4&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="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_valid?&lt;/span&gt;
    &lt;span class="n"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&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;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&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;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;
    &lt;span class="n"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kp"&gt;true&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;h4&gt;
  
  
  Do this
&lt;/h4&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="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:username&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_valid?&lt;/span&gt;
    &lt;span class="o"&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;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&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;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&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;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;Boolean expressions eventually resolve to either &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. Comparing them again to &lt;code&gt;true&lt;/code&gt; wastes computation and adds extra cognitive load without actually adding to the readability or explicitlness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not?
&lt;/h2&gt;

&lt;p&gt;Sometimes you don't always have a binary &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; values. For example, you can have &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;nil&lt;/code&gt; values in other languages. In which case, comparing them to &lt;code&gt;true&lt;/code&gt; do have a use because you want to avoid the other two (or three) possibility of the value not existing, or the value being &lt;code&gt;false&lt;/code&gt; at the same time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                  &lt;span class="c1"&gt;// default options `{}`&lt;/span&gt;
&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;    &lt;span class="c1"&gt;// explicit options&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;htmlEscape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may, however, confuses the reader because the absence of value is implicit in this context. Calling out implicitness usually improves readability but reduce succintness and adds conginitive load. So depending on your situation, shorter may be better or explicit may be better.&lt;/p&gt;

&lt;p&gt;One way to make this explicit is to split apart the two concerns in the code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checking for absence of value&lt;/li&gt;
&lt;li&gt;Checking for the value itself&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;htmlEscape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&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 code calls out to the reader to be on the lookout for the absence of values in the &lt;code&gt;options&lt;/code&gt; hash. That not all options maybe passed into the function.&lt;/p&gt;

&lt;p&gt;Alternatively, we can eliminate 1) entirely by supplying defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// now we are sure the 'escape` option will always be specified&lt;/span&gt;
  &lt;span class="c1"&gt;// our check is now straightforward&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;htmlEscape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An experienced coder will also notice that the pattern of "applying defaults" can be made more generic and applied uniformly throughout the codebase. This is exactly the usecase of &lt;a href="https://www.geeksforgeeks.org/lodash-_-defaults-method/"&gt;lodash's _.defaults() method&lt;/a&gt; which we can use to make the code more succinct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// eliminate any "absence of value" cases&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;htmlEscape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can avoid Lodash entirely and use null-coalescing operator &lt;code&gt;??&lt;/code&gt; if your language supports them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;escape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;htmlEscape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>style</category>
      <category>codequality</category>
    </item>
    <item>
      <title>[WIP] Write Better Code</title>
      <dc:creator>Chakrit Wichian</dc:creator>
      <pubDate>Wed, 17 Mar 2021 17:46:37 +0000</pubDate>
      <link>https://dev.to/prodigy9/write-better-code-3fgc</link>
      <guid>https://dev.to/prodigy9/write-better-code-3fgc</guid>
      <description>&lt;p&gt;This series is meant to be a collection of tips, tricks and techniques for writing a more readable and maintainable code. The content will &lt;strong&gt;focus exclusively on the style&lt;/strong&gt; and other subjective elements of code writing. There are already many other content on the web that talk about the semantics and how a piece of code or an algorithm "works". We focus, here, instead on how the code "reads".&lt;/p&gt;

&lt;p&gt;That being said, this does not mean we will forego the concern of making sure the code work entirely. We believe, rather, that correctly working code are a result of not only it having correct semantics, but also &lt;strong&gt;because the programmer writing/maintaining it can reason about it easily&lt;/strong&gt; because the code was written with such high readability standards.&lt;/p&gt;

&lt;p&gt;In other words, we believe making the code more readable makes it more correct as well.&lt;/p&gt;

&lt;p&gt;The content are purely derived from my own personal experience writing, reading and debugging unbelievable number of lines of code over 20+ years. Contributions are, of course, welcome and if this proves to be useful to many people, I'd be happy to open source and license it.&lt;/p&gt;

&lt;p&gt;Some of the content found here may feels familiar to readers of coding style books, but, again, I'd like to emphasize that this is distilled from my personal experience only and not summarized from any book. It also have no set plans or publishing schedule, I'll add to it as I have time and feel like I have something useful to contribute. Other times, it may stay static for months or years.&lt;/p&gt;

&lt;p&gt;I do believe, however, that there is an ultimate answer to all code styling issues. I believe that after a certain point in the career of programming and software development, most of us eventually come to the same or similar realization/conclusion. So it should be of no coincidence that some concepts found here may have already been explained in some book or some blog post somewhere on the interwebs. In which case , I'll add links and references to the relevant pages.&lt;/p&gt;

</description>
      <category>style</category>
      <category>codequality</category>
    </item>
    <item>
      <title>อยากได้เว็บไซต์ต้องทำไง</title>
      <dc:creator>Chakrit Wichian</dc:creator>
      <pubDate>Wed, 06 Nov 2019 06:27:38 +0000</pubDate>
      <link>https://dev.to/chakrit/-111c</link>
      <guid>https://dev.to/chakrit/-111c</guid>
      <description>&lt;p&gt;เขียนทิ้งไว้เป็น How-To แบบไวๆ เพราะรู้สึกชอบมีคนมาถาม และคำตอบที่เป็น Default ส่วนมากแม่งโคตรไม่เมกเซ้นส์ หรือว่าเป็นแบบคนจ้างสบาย ที่คนได้เว็บไปปวดหัว&lt;/p&gt;

&lt;p&gt;อย่างแรกที่สุดก่อนจะไปถึงว่าจ้างใคร เท่าไหร่ ใช้โปรแกรมไหน &lt;strong&gt;ตอบคำถามให้ได้ก่อนว่า อยากให้เว็บไซต์ทำอะไรให้เรา&lt;/strong&gt; ตัวอย่างเช่น:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;อยากให้ร้านดู Professional มากขึ้น&lt;/li&gt;
&lt;li&gt;อยากได้ Email แบบ @ชื่อร้าน.com&lt;/li&gt;
&lt;li&gt;อยากได้ช่องทางการขาย Online&lt;/li&gt;
&lt;li&gt;อยากมีที่ลงข้อมูลให้ลูกค้าอ่าน หรือติดต่อกลับ หรือ Google เจอ&lt;/li&gt;
&lt;li&gt;อยากได้ระบบช่วยสนับสนุนการทำงานในร้าน&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ที่ต้องถามเพราะว่า Solution ของแต่ละข้อนั้นมันไม่เหมือนกันเลย แต่ถ้าไม่ตอบคำถามนี้ก่อนแล้วตรงดิ่งไปหา　Freelance สิ่งที่เขาจะทำก็คือเขาก็จะให้ Solution ที่เขาถนัดมาแบบที่เขาเคยทำ แต่มันไม่ใช่สิ่งที่ดีสุดสำหรับร้านคุณแน่นอน หรือไม่ใช่สิ่งที่ถูกที่สุดด้วย แล้วเอาจริงๆ มันก็ไม่ใช่หน้าที่เขาที่จะต้องมาแนะนำว่าอะไรดีที่สุด เพราะส่วนมาก สายรับจ้างแบบนี้ เขาก็แค่รับ Requirement คุณมา ทำให้จบ แล้วจบกัน&lt;/p&gt;

&lt;p&gt;การหา Freelance มาทำเว็บให้ บอกเลยว่าเป็นคำตอบที่แย่ที่สุดแทบจะทุกครั้ง เหตุผลมีหลายข้อ:&lt;/p&gt;

&lt;h3&gt;
  
  
  Software ทุกตัวต้องการ Update ตลอดเวลา
&lt;/h3&gt;

&lt;p&gt;Software ทุกตัวมีช่องโหว่ทางด้านความปลอดภัยเสมอ และโดยปกติแล้วคนทำ Software เขาจะมีการอุดช่องโหว่พวกนี้เรื่อยๆ เป็นระยะ และเขาก็จะปล่อย Update มาเรื่อยๆ ทุกเดือน หรือบางตัวอาจจะเป็นทุกอาทิตย์เลยด้วยซ้ำ โดยเฉพาะอย่างยิ่งถ้าคุณใช้ Software ที่คนอื่นเขาให้กันดาดดื่นเช่น Wordpress นี่ตัวดีเลย เพราะใช้กันเยอะมากทั่วโลก&lt;/p&gt;

&lt;p&gt;ลองนึกดูว่าถ้าคุณเป็น Hacker แล้วคุณจะมานั่งเจาะเว็บไซต์ทีละเว็บไหม ถ้าคุณมีความรู้ช่องโหว่ของ Wordpress? ไม่เลย คุณก็ใช้วิธียิ่งกวาดไปเลยไง ถ้าคุณไปจ้าง Freelance ทำเว็บให้ แล้วเขาทำ Wordpress มาให้คุณต้องดูให้ดีๆ ว่าเขาตกลง Update ให้คุณไปตลอดการใช้งานไหม ถ้าคำตอบคือไม่ คุณเตรียมโดน Hack ได้เลย&lt;/p&gt;

&lt;p&gt;แล้วอย่าบอกว่าร้านคุณ "ไม่มีข้อมูลสำคัญให้ Hacker มาเจาะ" เพราะแค่เขายึด Domain ของคุณได้เขาก็เอาไปทำอะไรได้อีกร้อยแปดพันเก้าเลยครับ บางทีโดยที่คุณไม่รู้ตัวเลยด้วยซ้ำ ยกตัวอย่างง่ายๆ ว่าถ้าคุณเป็นร้านขายเสื้อผ้า แล้ววันนึงลูกค้าคุณได้รับ E-Mail ขายยาปลุกเซ็กส์ที่จั่วหัวเป็นชื่อร้านคุณ คุณคิดว่าเขาจะกลับมาซื้อร้านของคุณอีกไหม? รู้ตัวอีกทีธุรกิจ Online ก็พังแล้ว โดน Google แบนอีก ทั้งๆ ที่หน้าเว็บเปิดเข้าไปดูก็ไม่ได้เป็นอะไรเลย ทุกอย่างปกติเหมือนเดิม (เขาไม่อยากให้เรารู้ตัวไง เขาแค่อยากขโมย E-Mail มายิง Spam)&lt;/p&gt;

&lt;h3&gt;
  
  
  Software ชิ้นแรกไม่ใช่ Software ชิ้นสุดท้าย
&lt;/h3&gt;

&lt;p&gt;ถ้าคุณเคยได้ทำงานกับคน IT มาบ้าง จะต้องได้ยินคำว่า Agile ไม่มากก็น้อย ตอนนี้มันมีความหมายร้อยแปดพันเก้า แล้วแต่ว่าไปเรียนมาจากสำนักไหน แต่ข้อสำคัญที่คุณควรจะรู้ไว้เลยก็คือว่า &lt;strong&gt;สิ่งที่คุณคิดว่าคุณต้องการสำหรับร้านคุณในวันนี้ มันไม่ใช่สิ่งที่จำเป็นจริงๆ สำหรับคุณไปตลอดแน่นอน&lt;/strong&gt; ปีหน้า เดือนหน้า หรือแม้แต่แค่อาทิิตย์หน้า หรือพรุ่งนี้คุณอาจจะตื่นมาแล้วคิดได้ว่าจริงๆ คุณอยากได้ Function การทำงานอื่น ไม่ใช่สิ่งที่ทำไปแล้วด้วยซ้ำ&lt;/p&gt;

&lt;p&gt;ข้อสำคัญก็คือ Requirement ทางธุรกิจมันไม่เคยนิ่งอยู่แล้วครับ ถ้าคุณจ้าง Freelance มาทำให้แล้วคุณส่ง Requirement ไปหนึ่งชุด ถ้าคุณไม่ทบทวนให้ดี คิดให้แน่ Freelance เขาไม่มานั่งแคร์นะครับ ว่าสิ่งที่คุณระบุไปมันจะให้ได้จริงๆ เขาก็แค่ทำให้ดีที่สุดตามที่เขาเข้าใจ แล้วจ่ายเงินเมื่อไหร่ก็จบงาน ถ้าเกิดคุณนึกอยากจะเปลี่ยนอะไรขึ้นมาอีก ง่ายๆ ก็คือเสียเงินเพิ่มไปเรื่อยๆ ครับ&lt;/p&gt;

&lt;p&gt;ทุกจุดนึงธุรกิจของคุณจะแข็งเป็ก ปรับเปลี่ยนอะไรยากมาก เพราะว่าจะเปลี่ยนทีนึงต้องเสียเงิน เสียเวลา เสียอารมณ์ นั่งคุย นั่งประชุมกันหลายรอบ พวกนี้เป็นต้นทุนทั้งนั้น&lt;/p&gt;

&lt;p&gt;ถามว่า Freelance ดีๆ ที่คิดทุกอย่างให้ ดูแลให้ตลอดทางมีไหม มีครับ แต่คุณมีกำลังจ้างเขารึเปล่า คุณพร้อมจะจ่ายเงินหลักแสนเป็นรายเดือนไหม?&lt;/p&gt;

&lt;h3&gt;
  
  
  คุณไม่ใช่คนแรกที่อยากได้เว็บ
&lt;/h3&gt;

&lt;p&gt;คิดว่า ณ​ จุดนี้ทุกคนที่สามารถเปิดมาอ่านบล็อกนี้ได้ น่าจะใช้ Facebook, Twitter เป็นกันหมดแล้ว ลองคิดดูว่าถ้าธุรกิจคุณอยากได้หน้าร้าน หรืออยากได้อีเมล์ ธุรกิจอื่นๆ มันยากมากที่จะมองว่าความต้องการน้ีของธุรกิจของคุณมันเป็นเรื่อง Unique ที่ไม่มีใครเคยทำมาก่อน&lt;/p&gt;

&lt;p&gt;สิ่งที่จะบอกก็คือเดี๋ยวนี้มันมี Platform มากมายหลายอย่างให้เลือกใช้อยู่แล้ว แบบที่คลิกๆ แปปเดียวก็ใช้ได้เพราะฉะนั้นพวกนี้คือสิ่งที่คุณควรจะไปตามหาก่อนอย่างแรก ก่อนที่จะคิดว่าต้องจ้างใครมาทำเว็บให้ แถมการใช้งาน Platform พวกนี้มันมีข้อดีที่เน้นหนักมากๆ อยู่สามอย่างคือ&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;มันถูกกว่าจ้าง Freelance&lt;/strong&gt; เพราะว่าพวกนี้เขาทำ Software ทีเดียว บริการลูกค้าได้หลายคน ลองคิดดูว่าถ้าราคาจ้าง Freelance ของคุณคือ 15,000 บาทบวกกับความปวดหัวทั้งหลาย เงินก้อนนี้ถ้าเอาไปซื้อ Online Service หนึ่งตัว สมมุติว่าราคา $9.99 ต่อเดือน ก็ตีซะเดือนละ 400 คุณใช้งาน 37.5 เดือนหรือเทียบเป็นปีก็ 3 ปีเศษๆ เลยนะ!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;มันมี Function เพียบพร้อมมาให้แล้ว&lt;/strong&gt; ถ้าคุณไปจ้าง Freelance ทำ คุณก็ต้องไปนั่งไล่รายละเอียดของธุรกิจคุณให้ฟังทีละอย่าง ทำความเข้าใจให้ถูกต้องกัน กว่าจะรู้เรื่อง เริ่มทำกันได้ ก็เป็นเดือนแล้ว แถมนี่คือ Software ที่ทำขึ้นใหม่ มันมีข้อดีข้อเสียยังไง ก็ไม่มีใครรู้ ถ้าคุณไปใช้ Platform ที่คนอื่นเขาทำมาแล้ว คุณไม่ต้องมาเสียเวลาทำอะไรตรงนี้เลย เพราะเขาคิดมาให้หมดแล้ว มีลูกค้าคนอื่นของเขาที่เขาไปเรียนรู้มาแล้วว่าต้องมีอะไรบ้าง ต้องทำอะไรบ้าง เขาทำมาให้แล้ว คุณไม่ต้องไปคิดเองเลย แถมวันนึงถ้าเกิดคุณมีความต้องการใช้อะไรใหม่ๆ มันอาจจะมีคนทำไว้ให้แล้วตั้งแต่แรกด้วยซ้ำ คุณไม่ต้องไปแก้อะไรเลย แค่เข้าเว็บไปเปิดใช้ก็ใช้ได้แล้ว&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ผู้ให้บริการเขา Update ทุกอย่างให้คุณโดยอัตโนมัติ&lt;/strong&gt; คือเมื่อคุณใช้ Platform ร่วมกับคนอื่น อย่างเช่น Facebook อย่างนี้ เวลามีปัญหา มี Bug หรือมีช่องโหว่ด้านความปลอดภัย เขามี Incentive ในการเข้าไปแก้ให้คุณอยู่แล้ว เพราะมันกระทบลูกค้าเขาทุกคนพร้อมกัน คุณไม่ต้องรอให้ปัญหามันเกิด ไม่ต้องรอไปแจ้งให้ใครมาซ่อมให้&lt;/p&gt;

&lt;p&gt;เพราะฉะนั้นก่อนจะไปหาคนทำเว็บให้ ลองหา Service ออนไลน์ดูก่อนมันดีกว่ามากๆ&lt;/p&gt;

&lt;h1&gt;
  
  
  Common Services
&lt;/h1&gt;

&lt;p&gt;อันนี้เขียนทิ้งไว้เป็น List บริการออนไลน์ส่วนน้อยที่เราชอบเป็นการส่วนตัว เผื่อใครอยากกดเข้าไปใช้ ไปสมัครลองทำกันเอง&lt;/p&gt;

&lt;h3&gt;
  
  
  จดโดเมน
&lt;/h3&gt;

&lt;p&gt;ถ้าอยากมี Web Presence หรือมี .com .net .co.th เป็นของตัวเอง&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://domains.google/"&gt;https://domains.google/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.namecheap.com/"&gt;https://www.namecheap.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.thnic.co.th/"&gt;https://www.thnic.co.th/&lt;/a&gt; - สำหรับโดนเมนที่ลงท้ายด้วย .th&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ถ้าต้องจัดการ DNS (เช่นติดตั้ง E-Mail บนโดเมนของตัวเอง หรือมี Subdomain หลายๆ อย่าง หรือแค่อยากได้ WAF)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dnsimple.com/"&gt;https://dnsimple.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cloudflare.com/"&gt;https://www.cloudflare.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  อยากได้อีเมล์ @ชื่อร้าน
&lt;/h3&gt;

&lt;p&gt;ต้องจดโดเมนชื่อร้านก่อนนะ แล้วค่อยมา Setup ตรงนี้&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://gsuite.google.com/"&gt;https://gsuite.google.com/&lt;/a&gt; - ตัวมาตรฐาน หน้าตาเหมือน GMail แต่เป็น Domain เราเอง&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.zoho.com/"&gt;https://www.zoho.com/&lt;/a&gt; - อันนี้เป็นมวยรองแต่ใช้งานได้เหมือนกัน&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ทำการตลาดผ่าน E-Mail (ส่งข่าว แจ้งโปรฯ​ ฯลฯ)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.mailchimp.com/"&gt;https://www.mailchimp.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.campaignmonitor.com/"&gt;https://www.campaignmonitor.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  แชร์ E-Mail ตอบลูกค้าหลายๆ คนพร้อมกัน
&lt;/h3&gt;

&lt;p&gt;ถ้ามี Volume จำนวนปริมาณ E-Mail เยอะมาก แล้วพนักงานตอบกันไม่ทันหรือมีปัญหาแย่งกันตอบ ใครตอบอันไหน ลองใช้พวกนี้ดู&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.helpscout.com/"&gt;https://www.helpscout.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freshdesk.com/"&gt;https://freshdesk.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  อยากมีหน้าเว็บ หรือร้าน Online
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://wordpress.com/"&gt;https://wordpress.com/&lt;/a&gt; - ถ้าต้องใช้ Wordpress จริงๆ มาใช้ของต้นน้ำจากเจ้าของโดยตรงที่ตรงนี้ ให้เขา Host ให้ &lt;strong&gt;อย่าซ่า Host เอง!&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.shopify.com/"&gt;https://www.shopify.com/&lt;/a&gt; - เปิดร้านขายของ แพงหน่อยแต่ฟังก์ชั่นครบ ถ้าอยากได้ถูกไปใช้ WooCommerce บน Wordpress&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wix.com/"&gt;https://www.wix.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.squarespace.com/"&gt;https://www.squarespace.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  แชร์เอกสาร หรือทำ Workflow
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://products.office.com/th-th/business/small-business-solutions"&gt;https://products.office.com/th-th/business/small-business-solutions&lt;/a&gt; - ถ้าเน้นใช้ Office หนักๆ ต้องการแชร์ของกันทุกอาทิตย์ ไปลองกด Office 365 ดู ชีวิตจะสะดวกขึ้นเยอะ&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.google.com/"&gt;https://docs.google.com/&lt;/a&gt; - ตัวนี้แถมมากับ G-Suite เวลาติดอีเมล์ ถ้าไม่ได้ติดว่าต้องเป็น Microsoft Office แนะนำให้ใช้ตัวนี้ ไม่ต้องเสียตังค์เพิ่ม ออนไลน์ แชร์ง่าย โดยเฉพาะถ้าใช้ Android อยู่แล้วด้วย&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.dropbox.com/"&gt;https://www.dropbox.com/&lt;/a&gt; - สำหรับแชร์ไฟล์ทั่วไป หรือไฟล์ขนาดใหญ่ ที่ส่งผ่านเมล์ยาก&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://airtable.com/"&gt;https://airtable.com/&lt;/a&gt; - สำหรับสร้าง Workflow ตัวนี้ใช้ยากนิดนึง เหมือน Access สมัยก่อน แต่สมัครทีเดียวดัดแปลงได้ร้อยแปดพันเก้า&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;มีอีกแต่คิดว่าเท่านี้คง Cover เกิน 80% ของที่คนส่วนใหญ่ต้องการละ ถ้ามีอะไร E-Mail มาถามได้ &lt;a href="mailto:service@chakrit.net"&gt;service@chakrit.net&lt;/a&gt;&lt;/p&gt;

</description>
      <category>websites</category>
    </item>
    <item>
      <title>Multiple Identity Gitconfig (with GPG signing)</title>
      <dc:creator>Chakrit Wichian</dc:creator>
      <pubDate>Tue, 29 Oct 2019 16:12:40 +0000</pubDate>
      <link>https://dev.to/chakrit/multiple-identity-gitconfig-with-gpg-signing-8c0</link>
      <guid>https://dev.to/chakrit/multiple-identity-gitconfig-with-gpg-signing-8c0</guid>
      <description>&lt;p&gt;Have you ever had these problems like I did?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You work with multiple groups or companies, or you want to separate your work commits from your personal commits.&lt;/li&gt;
&lt;li&gt;You want to GPG sign all your commits.&lt;/li&gt;
&lt;li&gt;You do not put your personal GPG keys on your work machine, and you do not put your work GPG keys on your personal machine.&lt;/li&gt;
&lt;li&gt;You use a different GPG identity (and perhaps, email) for different repository.&lt;/li&gt;
&lt;li&gt;You synchronize your dotfiles regularly. It contains your GPG configuration as well as your global .gitconfig and use the same dotfiles repository on both your work machine and your personal machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you did you'll find out that you now have a conflict in your &lt;code&gt;.config/git/config&lt;/code&gt; file, namely in the &lt;code&gt;[user]&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;I have mine, looking something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[user]&lt;/span&gt;
  &lt;span class="py"&gt;name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Chakrit Wichian&lt;/span&gt;
  &lt;span class="py"&gt;email&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;service@chakrit.example.net&lt;/span&gt;
  &lt;span class="py"&gt;signingkey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;E888C1BC6A4DB2F4  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this tells git, for all my &lt;strong&gt;personal projects&lt;/strong&gt;, to use my &lt;strong&gt;personal email&lt;/strong&gt; and &lt;strong&gt;personal GPG key&lt;/strong&gt; to sign it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fchakrit-public.us-east-1.linodeobjects.com%2F2019-10-29-verified-commits.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fchakrit-public.us-east-1.linodeobjects.com%2F2019-10-29-verified-commits.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This all works nice and well but then, how do we setup our work accounts?&lt;/p&gt;

&lt;p&gt;Previously I have used &lt;a href="https://www.gnu.org/software/stow/" rel="noopener noreferrer"&gt;GNU Stow&lt;/a&gt; with multiple &lt;code&gt;git&lt;/code&gt; folder in my dotfiles repository and only &lt;code&gt;stow&lt;/code&gt; the one I needed into place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# on personal machine&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;dotfiles &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; stow git-personal

&lt;span class="c"&gt;# on work machine&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;dotfiles &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; stow git-work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously, though, this approach has an annoying flaw: I cannot synchronize changes easily across all git installations I use.&lt;/p&gt;

&lt;p&gt;That got me thinking. What is the &lt;em&gt;BEST&lt;/em&gt; approach to this problem? Usually other configuration system have a way to &lt;code&gt;include&lt;/code&gt; files so that you can split them into bits and keep most of the shared configuration items the same in the main file and include the parts that are different from other files.&lt;/p&gt;

&lt;p&gt;I could modify my workflow so that I have a main configuration that is shared for all installations and have another &lt;code&gt;supplemental&lt;/code&gt; configs just for the specific machine I happen to be on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# shared configuration&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;dotfiles &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; stow git-base &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~
tree

&lt;span class="nb"&gt;.&lt;/span&gt;
└── .config
    ├── git
    │   ├── config &lt;span class="c"&gt;# ← contains an include directive.&lt;/span&gt;
    │   └── ignore
    └── hub

2 directories, 3 files

&lt;span class="c"&gt;# selecting the right "extra" to install&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;dotfiles &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; stow git-company-x &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ~
tree

&lt;span class="nb"&gt;.&lt;/span&gt;
└── .config
    ├── git
    │   ├── config
    │   ├── extras &lt;span class="c"&gt;# ← contains extras, for company X&lt;/span&gt;
    │   └── ignore
    └── hub

2 directories, 4 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So after realizing this, I began to search for git configuration documentation, seeing if this functionality is available.&lt;/p&gt;

&lt;p&gt;To my surprise, the &lt;a href="https://git-scm.com/docs/git-config#_includes" rel="noopener noreferrer"&gt;git manual on includes&lt;/a&gt; has an &lt;a href="https://git-scm.com/docs/git-config#_conditional_includes" rel="noopener noreferrer"&gt;&lt;em&gt;EVEN BETTER&lt;/em&gt; solution&lt;/a&gt; lying in wait for me with the &lt;code&gt;includeIf&lt;/code&gt; directive.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conditional Includes
&lt;/h1&gt;

&lt;p&gt;Git supports a neat way of specifying an &lt;code&gt;includeIf&lt;/code&gt; condition by selecting based on the &lt;strong&gt;location of the .git dir&lt;/strong&gt;. And better yet, it also supports &lt;code&gt;**&lt;/code&gt; directory globbing.&lt;/p&gt;

&lt;p&gt;This means that you can structure your workspace such that all of Company X's work are under a dir named &lt;code&gt;company-x&lt;/code&gt; and then using a condition matching &lt;code&gt;**/company-x/**/.git&lt;/code&gt; to match all git checkouts under that dir.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;, if you havn't already, you need to reorganize your repos based on where you work (or how you want to apply gitconfigs):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# example directory tree under your `git/` or something.&lt;/span&gt;
tree

&lt;span class="nb"&gt;.&lt;/span&gt;
├── company-x
│   ├── hello-world
│   └── awesome-project
└── personal
    ├── hello-world
    └── awesome-learning
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt;, create multiple git configuration files for each different situation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# config.personal
&lt;/span&gt;&lt;span class="nn"&gt;[user]&lt;/span&gt;
  &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Chakrit Wichian&lt;/span&gt;
  &lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;service@chakrit.example.net&lt;/span&gt;
  &lt;span class="py"&gt;signingkey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;E888C1BC6A4DB2F4&lt;/span&gt;

&lt;span class="c"&gt;# config.company-x
&lt;/span&gt;&lt;span class="nn"&gt;[user]&lt;/span&gt;
  &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Chakrit Wichian&lt;/span&gt;
  &lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;chakrit@company-x.example.com&lt;/span&gt;
  &lt;span class="py"&gt;signingkey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;3CDC219617574C11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Third&lt;/strong&gt;, in your main git configuration file, adds as many &lt;code&gt;includeIf&lt;/code&gt; directive as needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# default case
&lt;/span&gt;&lt;span class="nn"&gt;[include]&lt;/span&gt;
  &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;config.personal&lt;/span&gt;

&lt;span class="c"&gt;# when working with company-x
&lt;/span&gt;&lt;span class="nn"&gt;[includeIf "gitdir:**/company-x/**/.git"]&lt;/span&gt;
  &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;config.company-x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lastly&lt;/strong&gt;, save all files and test them out!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;chakrit/secret-project-x
git config user.email
service@chakrit.example.net &lt;span class="c"&gt;# ← outputs personal email!&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; ../../company-x/awesome-product-y
git config user.email
chakrit@company-x.example.com &lt;span class="c"&gt;# ← outputs work email!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some other uses that I think is cool follows:&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatically switching &lt;code&gt;hub&lt;/code&gt; context.
&lt;/h3&gt;

&lt;p&gt;If the companies you work for uses &lt;a href="https://github.com/enterprise" rel="noopener noreferrer"&gt;GHE&lt;/a&gt;. You could point the &lt;a href="https://github.com/github/hub" rel="noopener noreferrer"&gt;&lt;code&gt;hub&lt;/code&gt; CLI&lt;/a&gt; to different domains base on where the repo is placed on your system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# config.company-x
&lt;/span&gt;&lt;span class="nn"&gt;[hub]&lt;/span&gt;
  &lt;span class="py"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;git.company-x.example.com&lt;/span&gt;

&lt;span class="c"&gt;# config.company-y
&lt;/span&gt;&lt;span class="nn"&gt;[hub]&lt;/span&gt;
  &lt;span class="py"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;git.company-y.example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Different signing settings base on branch.
&lt;/h3&gt;

&lt;p&gt;Aside from the &lt;code&gt;gitdir:&lt;/code&gt; matching condition, you can also use &lt;code&gt;onbranch:&lt;/code&gt; to setup branch-specific configs!&lt;/p&gt;

&lt;p&gt;If you have specific branch system setup, for example &lt;code&gt;master&lt;/code&gt; for production commits, you could set it up so that GPG signing is only done there and only require commits on that branch to have proper verification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# config
&lt;/span&gt;&lt;span class="nn"&gt;[commit]&lt;/span&gt;
  &lt;span class="py"&gt;gpgsign&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;false&lt;/span&gt;
&lt;span class="nn"&gt;[includeIf "onbranch:master"]&lt;/span&gt;
  &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;config.master&lt;/span&gt;

&lt;span class="c"&gt;# config.master
&lt;/span&gt;&lt;span class="nn"&gt;[commit]&lt;/span&gt;
  &lt;span class="py"&gt;gpgsign&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading! Ping me on Twitter and say hi :)&lt;/p&gt;

</description>
      <category>git</category>
      <category>gpg</category>
      <category>gitconfig</category>
      <category>identity</category>
    </item>
  </channel>
</rss>
