<?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: Karra Raghu Ram</title>
    <description>The latest articles on DEV Community by Karra Raghu Ram (@tejaram15).</description>
    <link>https://dev.to/tejaram15</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%2F680591%2Fe3490215-28be-4813-84a2-70ba7445cffb.jpeg</url>
      <title>DEV Community: Karra Raghu Ram</title>
      <link>https://dev.to/tejaram15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tejaram15"/>
    <language>en</language>
    <item>
      <title>Build a basic key-value store</title>
      <dc:creator>Karra Raghu Ram</dc:creator>
      <pubDate>Wed, 01 Sep 2021 11:42:19 +0000</pubDate>
      <link>https://dev.to/tejaram15/build-a-basic-key-value-store-1f54</link>
      <guid>https://dev.to/tejaram15/build-a-basic-key-value-store-1f54</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;When life is hard take it back to the basics. - Alex Daniel&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let us consider the world's simplest database implemented as 2 functions &lt;strong&gt;f(x)&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;helpers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./helper.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;helpers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeToFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ex&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="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="k"&gt;return&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;helpers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Log the exception&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;These 2 functions implement the key-value store. We can call the setValue function which will store the value associated to a key. The key and value can be any string [1]. We can then call the getValue function to get the most recent value that was assigned to a key.&lt;/p&gt;

&lt;p&gt;And it works surprisingly well😍😍:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"name":"tejaram15","likes":["Suits","Avengers"]}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tejaram15&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;likes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Suits&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Avengers&lt;/span&gt;&lt;span class="dl"&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 underlying storage is basically a text file storing all the information row by row. setValue appends a key-value pair to the end of a text file. getValue searches for the last written key-value pair and returns the value for a given key🔑🔑.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thought process
&lt;/h2&gt;

&lt;p&gt;Even though this is the most basic implementation possible understanding the thought process is the crux of this series. &lt;/p&gt;

&lt;p&gt;I initially implemented the &lt;code&gt;app.js&lt;/code&gt; file which abstracted away all the details and was expecting 2 functions which would do all the work for me. These are helper functions and the implementation can be different based on where we are importing them from. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lesson 1: Always implement the functional requirements(or API specs) on a high level first and then implement the underlying details. This helps in keeping breaking your code into blocks and its easier to implement.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I then moved on to &lt;code&gt;helper.js&lt;/code&gt; which would hold the actual low level implementation details. The first thing i implemented is the &lt;code&gt;writeToFile&lt;/code&gt; function. While searching google for the query &lt;em&gt;"node js append to a file"&lt;/em&gt; i found the &lt;code&gt;fs.writeFileSync&lt;/code&gt; API [3]. I implemented a function that took in a string &lt;code&gt;data&lt;/code&gt; and appended this to the end of a file with path &lt;code&gt;FILE_NAME&lt;/code&gt;. This was a good time to start unit testing because i already had a concrete implementation for one of the core low level functions. I used mocha for unit-testing in nodejs but there are many other options. I implemented the write test first and started testing the function. Some bug fixes later i was able to see that the function was working correctly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lesson 2: Always write unit-tests as soon as you implement a function. This will improve the overall test coverage as you won't miss anything un-intentionally. And also make sure you aren't missing any important assumptions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I implemented the &lt;code&gt;readFromFile&lt;/code&gt; function next which had multiple steps to it. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First read the file through the &lt;code&gt;fs.readFileSync&lt;/code&gt; API [4].&lt;/li&gt;
&lt;li&gt;Split the data received into multiple lines.&lt;/li&gt;
&lt;li&gt;Reverse those lines (as we are interested in the last inserted key).&lt;/li&gt;
&lt;li&gt;Split these lines by a separator (",").&lt;/li&gt;
&lt;li&gt;Check if the current &lt;code&gt;key&lt;/code&gt; matches with the &lt;code&gt;searchKey&lt;/code&gt; and return the &lt;code&gt;value&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I then implemented the unit tests for it and pushed the code repository after completing basic tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time complexity analysis
&lt;/h2&gt;

&lt;p&gt;You might have already figured out the time complexity of the operations supported by our key-value store. &lt;code&gt;setValue&lt;/code&gt; takes &lt;strong&gt;O(1)&lt;/strong&gt; time in every case and &lt;code&gt;getValue&lt;/code&gt; takes &lt;strong&gt;O(n)&lt;/strong&gt; time in the worst case. This isn't the best possible solution. Also since the data is always being written to a single file the size of the file keeps growing infinitely. &lt;/p&gt;

&lt;p&gt;We could improve the time-complexity of the reads by maintaining an index of all the keys we are storing in the database. This will be the topic of our next article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes and References
&lt;/h2&gt;

&lt;p&gt;[1] String is used because it is easier to serialize and de-serialize. Additional serialisation will be required if we want to save other primitive types or complex objects.&lt;/p&gt;

&lt;p&gt;[2] Repository link🔗🔗: &lt;a href="https://github.com/tejaram15/kvstore/tree/basic-kv-store"&gt;https://github.com/tejaram15/kvstore/tree/basic-kv-store&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[3] fs.writeFileSync API🔗🔗: &lt;a href="https://www.geeksforgeeks.org/node-js-fs-writefilesync-method/"&gt;https://www.geeksforgeeks.org/node-js-fs-writefilesync-method/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] fs.readFileSync API🔗🔗: &lt;a href="https://www.geeksforgeeks.org/node-js-fs-readfilesync-method/"&gt;https://www.geeksforgeeks.org/node-js-fs-readfilesync-method/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] Notion Link: &lt;a href="https://cooing-entrance-644.notion.site/Build-a-basic-key-value-store-b6470cb9036040faa53eed94e668c61a"&gt;Notion Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✌🏻✌🏻&lt;/p&gt;

&lt;p&gt;Peace.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>database</category>
    </item>
    <item>
      <title>Functional wisdom for software engineers</title>
      <dc:creator>Karra Raghu Ram</dc:creator>
      <pubDate>Wed, 25 Aug 2021 09:57:54 +0000</pubDate>
      <link>https://dev.to/tejaram15/functional-wisdom-for-software-engineers-133f</link>
      <guid>https://dev.to/tejaram15/functional-wisdom-for-software-engineers-133f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The beginning is the most important part of the work.  - PLATO&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Motivation✨✨
&lt;/h2&gt;

&lt;p&gt;The average article intended for a software engineer fails to impart one key element to the readers - "Inference" or "Deduction". &lt;/p&gt;

&lt;p&gt;Let's take a Key-Value store for example 🔥. Initial search gives us definitions, advantages-disadvantages and some interview design tutorials. All these articles provide sometimes rich but shallow information that might be relevant to perform well in an interview but leave us in an inconsistent state🤷🏻‍♂️🤷🏻‍♀️.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;process&lt;/strong&gt; of building a software project has been sparsely communicated and for the most part stayed hidden in the software engineering community🏴‍☠️🏴‍☠️.&lt;/p&gt;

&lt;p&gt;The creators of these articles and videos consistently ignore to mention their deductions and just present the results like a scientific study📖📖. They fail to impart the wisdom to come up with such ideas, make assumptions, document them, implement and test them, discuss the cases when the above assumptions could be wrong, and re-iterate the whole process again.&lt;/p&gt;

&lt;p&gt;This blog is my attempt to bridge this gap🔧🔧.&lt;/p&gt;

&lt;h2&gt;
  
  
  My personal framework💪🏻💪🏻
&lt;/h2&gt;

&lt;p&gt;This is the framework i use while working on a project. These steps will be common across all kinds of software engineering roles.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Coming up with an idea🤔🤔.&lt;/li&gt;
&lt;li&gt;Gathering the requirements🕵🏻‍♀️🕵🏻‍♂️.&lt;/li&gt;
&lt;li&gt;Making appropriate assumptions😅😅.&lt;/li&gt;
&lt;li&gt;Creating a high level design &amp;amp; low level design👨🏻‍💻👩🏻‍💻.&lt;/li&gt;
&lt;li&gt;Take feedback from peers👏🏻👏🏻&lt;/li&gt;
&lt;li&gt;Implementing the code🤠🤠.&lt;/li&gt;
&lt;li&gt;Testing the implementation🤮🤮.&lt;/li&gt;
&lt;li&gt;Verifying assumptions and coming up with anti-assumptions✅❌.&lt;/li&gt;
&lt;li&gt;Iterating all over again🔃🔃🔃🔃.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Types of software design
&lt;/h2&gt;

&lt;p&gt;There are majorly 2 ways in which a software could be designed. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Top-down ⬇️⬇️&lt;/li&gt;
&lt;li&gt;Bottom-up ⬆️⬆️&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the Top-down approach we start with a somewhat concrete set of requirements, number of users, API model and some other relevant assumptions. We then start building the High level design and Low level design to match the requirements. This method ensures that we are not drifting off an actual goal as the requirements are almost fixed and works great in a corporate environment🏦🏦.&lt;/p&gt;

&lt;p&gt;In the Bottom-up approach we start from the absolute basic level of the problem we try to solve. We then take try to find bottle-necks which may occur when we throw more users and more work. We then tweak our initial design or sometimes completely re-do it and arrive at a point where we repeat the steps all over again📷📷.&lt;/p&gt;

&lt;h3&gt;
  
  
  The risk of diminishing returns
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;80% of effects come from 20% of causes and 80% of results come from 20% of effort.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every software has its limits, there is no perfect software that fits all needs. At some point in following the above framework a question arises: &lt;strong&gt;When should we stop?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;When the rewards are too low from the effort that needs to be put in. I simply call it the "Effort-Reward" ratio. If it is in the favour of new improvements then you should go ahead with the changes else think twice before investing your time in improving the software.&lt;br&gt;
With this I leave you readers with the anticipation of the next post in my blog.&lt;/p&gt;

&lt;p&gt;✌🏻&lt;br&gt;
Peace.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
