<?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: igaurab</title>
    <description>The latest articles on DEV Community by igaurab (@igaurab).</description>
    <link>https://dev.to/igaurab</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%2F201410%2F538b98b2-969d-4e82-a4ab-61f70837683e.jpg</url>
      <title>DEV Community: igaurab</title>
      <link>https://dev.to/igaurab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igaurab"/>
    <language>en</language>
    <item>
      <title>How to write a good function?</title>
      <dc:creator>igaurab</dc:creator>
      <pubDate>Sun, 30 May 2021 11:02:12 +0000</pubDate>
      <link>https://dev.to/igaurab/how-to-write-a-good-function-464d</link>
      <guid>https://dev.to/igaurab/how-to-write-a-good-function-464d</guid>
      <description>&lt;p&gt;Here are my 3 things to look out for while writing a good function. The code examples are given in python but the concept applies across all the programming languages. If you have any other ideas/strategies please mention them in the comments. &lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Trust The Inputs
&lt;/h3&gt;

&lt;p&gt;Look at the code below and think about what can go wrong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def process_date(str_date):
    """
       This takes date in format dd/mm/yyyy and returns
       a dict of format {'y':2000,'m':10,'d':19 } as output
    """
    d,m,y = str_date.split('/')
    value = {'y':y,'m':m,'d':d}
    return value

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, the code seems to work fine. If you run the function&lt;/p&gt;

&lt;p&gt;&lt;code&gt;process_date(str_date = 10/20/2000)&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Then the output of the function will be:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{'y' : 2000,'m' : 20, 'd' : 10}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The function returns an output so everything seems to be working right? But there is a logical error. Months can never be greater than 12. The same goes for days and years. Apart from that what if the user passed negative values&lt;code&gt;-1/-1/-1&lt;/code&gt;? Also, what if the user provided an empty string?&lt;/p&gt;

&lt;p&gt;Here, we made a mistake of &lt;strong&gt;trusting the inputs&lt;/strong&gt;. We should &lt;strong&gt;never&lt;/strong&gt; trust the inputs. Be skeptical about the parameters and think hard about the edge cases. Make sure to sanitize your input before you perform any computation on them. &lt;/p&gt;




&lt;h3&gt;
  
  
  Fail Loudly and Clearly
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What if you change the format of the date?&lt;/strong&gt; From &lt;code&gt;10/20/2000&lt;/code&gt; to &lt;code&gt;10-20-2000&lt;/code&gt;. This would completely break your code. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GMxivlex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622096113415/WUj9cCcH_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GMxivlex--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622096113415/WUj9cCcH_.png" alt="image.png" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, when the input is not what we want them to be, we want to notify the user about this issue. And if we have to fail, choose to fail loudly and clearly. The above error message is quite not clear compared to the one below, which clearly mentions that the issue is because of the input format of date supplied&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;regex_date_format = "^\d{1,2}/\d{1,2}/\d{4}$"
if not re.match(regex_date_format, date_str):
    raise ValueError(
        f"str_date: {str_date} should be of the format dd/mm/yyyy "
    )

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, Most of the time, we tend to simply return &lt;code&gt;None&lt;/code&gt; if we get any error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if error:
    return None

if error:
    return None

some code

return result

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This especially causes issue while debugging the program. In above dummy program, if we get a &lt;code&gt;None&lt;/code&gt; as output, then which error in particular gave us the &lt;code&gt;None&lt;/code&gt; value? &lt;br&gt;
So, being loud and clear about the errors that occurs in program helps other developers and users of the function to understand what it is that is causing the issue/error.&lt;/p&gt;


&lt;h3&gt;
  
  
  Be consistent with return type
&lt;/h3&gt;

&lt;p&gt;One thing I like about statically typed language is their consistency. If you are using a function then you'll know if that will return an &lt;code&gt;array&lt;/code&gt; or a &lt;code&gt;dict&lt;/code&gt; or an &lt;code&gt;string&lt;/code&gt; etc. This allows us to process the output in some consistent manner and also avoids confusion and bugs in the program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def return_something( input ):
    if error:
        return 'Error connecting to the server'
    code

    return {"data":"Hello world"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose someone uses this function in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
response = return_something(inp)
data = response['data']

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the code breaks if there is any error while connecting to the server. The right way of checking it would be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;response = return_something(inp)
if isinstance(response, str):
    handle_error
data = response['data']

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other way to write the same function would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def return_something( input ):
    if error:
        return {"error": 'Error connecting to the server' , "data": "" }
    code

    return {"data":"Hello world", "error": "" }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In both cases we get the same fields, this helps us be consistent with the way we process the data further in out code, and should not worry if we get a string or an array etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;response = return_something(inp)
data = response['data']
error = response['error']

if error:
   handle_error

if data:
   do_something

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This increases the code readability also. In the first example, one could wonder, &lt;strong&gt;why is it that we are handling the error if the instance is a string&lt;/strong&gt;. Whereas in the second implementation it's clear that any response contains two fields the &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; and if we get any error we can do some error handing.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Please provide your feedback&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>codenewbie</category>
      <category>codequality</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Dockerfile good practices [NOTE]</title>
      <dc:creator>igaurab</dc:creator>
      <pubDate>Tue, 04 May 2021 08:58:12 +0000</pubDate>
      <link>https://dev.to/igaurab/dockerfile-good-practices-note-ad8</link>
      <guid>https://dev.to/igaurab/dockerfile-good-practices-note-ad8</guid>
      <description>&lt;p&gt;This is my note from this this talk on &lt;a href="https://www.youtube.com/watch?v=JofsaZ3H1qM"&gt;Dockerfile good practices&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Areas of improvements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Incremental build time&lt;/li&gt;
&lt;li&gt;Image size&lt;/li&gt;
&lt;li&gt;Maintainability&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Consistency / Repeatability&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Incremental build time
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#leverage-build-cache"&gt;Making build cache your friend&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Order is important&lt;/strong&gt;: if  you make changes to any line or any stage of your dockerfile then subsequent stages cache will be busted. So, order your steps from least to most frequently changing steps to optimize caching.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at this sample dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM ubuntu:18.04
COPY . /app
RUN apt-get update
RUN apt-get install openjdk-8-jdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This dockerfile copies the application files immediately after the start. Because caching is based on previous steps, whenever something changes in that content, all the steps after the copy has to be invalidated. So, the cache will have to be busted and the steps below should run again.&lt;/p&gt;

&lt;p&gt;This is a problem here, since if you want to change your application code, and want to build your image reflecting the latest change, you'll have run all the commands below the COPY command.&lt;br&gt;
A better way here, would be to run the &lt;code&gt;COPY&lt;/code&gt; command at the last.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install openjdk-8-jdk
COPY . /app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Only copy what's needed&lt;/strong&gt; Avoid &lt;code&gt;COPY .&lt;/code&gt; if possible. When you are copying files into your image make sure you're very specific as to what you want to copy, because any changes to files you're copying will bust the cache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Identify cacheable units&lt;/strong&gt; Sometimes you want things to be cached together. Identify cacheable units. For example change this&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN apt-get update
RUN apt-get -y install openjdk-8-jdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN apt-get update \

 &amp;amp;&amp;amp; apt-get -y install \
     openjdk-8-jdk

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents using an outdated package cache.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fetch dependencies in a separate step:&lt;/strong&gt; This is also about identifying the cacheable units.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reduce Image size
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remove unnecessary dependencies:&lt;/strong&gt; Don't install debugging tools and other unnecessary dependencies. You can also use the &lt;code&gt;--no-install-recommends&lt;/code&gt; flag. You don't want to deploy your build tools into production, as you will not need them at runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remove package manager cache:&lt;/strong&gt; You don't need the cache after installing the packages. It's good to remove them as well&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN apt-get update \ 
    &amp;amp;&amp;amp; apt-get -y install --no-install-recommends \ 
    openjdk-8-jdk \ 
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Maintainability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use official images where possible&lt;/strong&gt;: Official images are pre-configured for container use and built by smart people. It can save you a lot of time in maintenance. This also allows you to share layers between images, as they use exactly the same base image. &lt;br&gt;
For the above sample Dockerfile instead of using debain and installing the dependencies simply start your base image from &lt;code&gt;FROM openjdk:8&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use more specific tags&lt;/strong&gt;: The &lt;code&gt;latest&lt;/code&gt; tag is a rolling tag. Be specific to prevent unexpected changes in your base image. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Look for minimal flavors&lt;/strong&gt; Maybe you don't need all the things that is in the bigger variants.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPOSITORY  TAG             SIZE
-----------------------------------------
openjdk     8               624MB
openjdk     8-jre           443MB
openjdk     8-jre-slim      204MB
opendjk     8-jre-alpine    83MB

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reproducible
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;The dockefile as a blueprint of your image, source code the source of truth for your application&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Make the dockerfile your blueprint&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It describes the build environment&lt;/li&gt;
&lt;li&gt;Correct versions of build tools installed&lt;/li&gt;
&lt;li&gt;Prevent inconsistencies between environments&lt;/li&gt;
&lt;li&gt;There may be system dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Multi-stage builds
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Use Cases
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Separate build from runtime environment&lt;/li&gt;
&lt;li&gt;Slight variations on images (DRY)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Build dev/test/lint/ specific environments&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;builder: all build dependencies&lt;/li&gt;
&lt;li&gt;build: builder + build artifacts&lt;/li&gt;
&lt;li&gt;cross: same as build but for different envs&lt;/li&gt;
&lt;li&gt;dev: builder + dev/debug tools&lt;/li&gt;
&lt;li&gt;lint: minimal lint dependencies&lt;/li&gt;
&lt;li&gt;test: all test dependencies + build artifacts to be tested&lt;/li&gt;
&lt;li&gt;release: final minimal image with build artifacts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delinearizing your dependencies (concurrency)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Platform specific stages&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you name a stage you can only build that stage.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FROM image_or_stage AS stage_name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ docker build --target stage_name&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Resources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.docker.com/blog/intro-guide-to-dockerfile-best-practices/"&gt;Dockerfile best practices&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices"&gt;Docker's official best practices&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>personal</category>
      <category>notes</category>
    </item>
    <item>
      <title>How to find the name of the package which includes your missing header file</title>
      <dc:creator>igaurab</dc:creator>
      <pubDate>Fri, 02 Apr 2021 10:20:57 +0000</pubDate>
      <link>https://dev.to/igaurab/how-to-find-the-name-of-the-package-which-includes-your-missing-header-file-kpe</link>
      <guid>https://dev.to/igaurab/how-to-find-the-name-of-the-package-which-includes-your-missing-header-file-kpe</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RKGvCKOF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1617009441530/467xPEI5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RKGvCKOF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1617009441530/467xPEI5g.png" alt="error.png" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While I was installing  &lt;a href="https://github.com/igaurab/dwm"&gt;my dwm&lt;/a&gt; build, i got a couple errors like the one shown in figure above. The header files which the dwm build needed were missing. The problem here is different linux distributions contains these header files under different package names. This solution works for debain or apt package manager.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;apt-file&lt;/code&gt; can be used to search for the package name where the header file is located. &lt;code&gt;apt-file&lt;/code&gt; is not installed by default. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt install apt-file&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xYAIhNzE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1617009736727/43-Xijn8I.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xYAIhNzE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1617009736727/43-Xijn8I.png" alt="finding.png" width="749" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we have installed the &lt;code&gt;apt-file&lt;/code&gt; we can simply look for the name of the package where the header file is located. The name of the package I needed to install was &lt;code&gt;libxinerama-dev&lt;/code&gt; Once we have the name of the package we can simply install it using apt.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt install libxinerama-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jKFzgOCS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1617009997547/eEXOa9CH1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jKFzgOCS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1617009997547/eEXOa9CH1.png" alt="done_installed.png" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that try to compile the file again and repeat the process until you are done.&lt;/p&gt;

</description>
      <category>linux</category>
    </item>
  </channel>
</rss>
