<?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: Amir Helali</title>
    <description>The latest articles on DEV Community by Amir Helali (@ahelali).</description>
    <link>https://dev.to/ahelali</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%2F1156801%2F1c426b45-81ae-47f7-826e-0266ba9b84bb.png</url>
      <title>DEV Community: Amir Helali</title>
      <link>https://dev.to/ahelali</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahelali"/>
    <language>en</language>
    <item>
      <title>My Latest Contribution to ChatCraft</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Tue, 12 Dec 2023 02:44:23 +0000</pubDate>
      <link>https://dev.to/ahelali/my-latest-contribution-to-chatcraft-4lg8</link>
      <guid>https://dev.to/ahelali/my-latest-contribution-to-chatcraft-4lg8</guid>
      <description>&lt;h2&gt;
  
  
  Latest Changes
&lt;/h2&gt;

&lt;p&gt;So, to pick up where I left off from my previous post, I was able to stick to my plan of using the &lt;code&gt;Strategy Pattern&lt;/code&gt; within the functional component paradigm structure instead of class component paradigm. Here are the changes I made to the code base to reflect my plan: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I created an &lt;code&gt;interface&lt;/code&gt; function which defines the structure for my response handling functions:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ResponseHandlerStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;I created a &lt;code&gt;responseHandler&lt;/code&gt; which is in charge of selecting the right response handler function based on the boolean &lt;code&gt;streaming&lt;/code&gt; flag:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responseHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponseHandlerStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;streaming&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;handleStreamingResponse&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;handleNonStreamingResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;I created 2 different implementations for handling the responses. One is for handling an streaming response and the other is for handling a non-streaming response:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleStreamingResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponseHandlerStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;streamResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChatCompletionChunk&lt;/span&gt;&lt;span class="o"&gt;&amp;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="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;streamChunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;streamResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseOpenAIChunkResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;streamChunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;streamOpenAIResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionArgs&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&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;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handleOpenAIResponse&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;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;functionArgs&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleNonStreamingResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ResponseHandlerStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChatCompletion&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="kd"&gt;const&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;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;functionArgs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseOpenAIResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handleOpenAIResponse&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;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;functionArgs&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;ul&gt;
&lt;li&gt;Implemented the above functions in the main &lt;code&gt;chatWithLLM&lt;/code&gt; function and modified the code base to support these functions within a single code path:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;[...]&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responsePromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;chatCompletionParams&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ChatCompletionCreateParamsStreaming&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;chatCompletionReqOptions&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;responseHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handleError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&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="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleCancel&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responsePromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;togglePause&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;ul&gt;
&lt;li&gt;&lt;p&gt;Ran the application to make sure that these new functions were working correctly and didn't break the overall functionality of the program.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Formatted the code with Prettier via VSCode, committed my changes, and created a &lt;a href="https://github.com/tarasglek/chatcraft.org/pull/304"&gt;PR&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Leveraged
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I used the OpenAI API &lt;a href="https://platform.openai.com/docs/api-reference/chat"&gt;&lt;code&gt;chat&lt;/code&gt;&lt;/a&gt; documentation to familiarize myself with and understand different chat objects, types of responses, and the different return types.&lt;/li&gt;
&lt;li&gt;I researched the &lt;code&gt;strategy pattern&lt;/code&gt; and its application in Typescript from different sources online.&lt;/li&gt;
&lt;li&gt;I used the comments and the feedbacks provided in a previous &lt;a href="https://github.com/tarasglek/chatcraft.org/pull/220#discussion_r1299371774"&gt;PR&lt;/a&gt; for the project that were related to the issue I worked on. I used these to understand what was needed for me to do and the overall logic and the structure of the code base.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;At first I was a bit intimidated to contribute to a larger project. However, I am happy that I jumped into it with a plan which guided me throughout my contribution. I am happy that my original plan worked out, even though I had to change my approach to fit the functional structure of the code-base. I am glad that I got to work on a project which used OpenAI API so I could learn more about it. Also, I am happy that I got to use a design pattern that I had learned theoretically but never had the chance to apply it in Typescript. I am still waiting for my PR to be reviewed, and based on the feedback, if there are any changes needed, I will make sure to address them with appropriate adjustments.  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Chatcraft Runtime Response Handling Progress</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Mon, 11 Dec 2023 00:22:44 +0000</pubDate>
      <link>https://dev.to/ahelali/chatcraft-runtime-response-handling-progress-295i</link>
      <guid>https://dev.to/ahelali/chatcraft-runtime-response-handling-progress-295i</guid>
      <description>&lt;h2&gt;
  
  
  Progress So Far
&lt;/h2&gt;

&lt;p&gt;So, in my previous post I explained my plan to contribute to an &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/227"&gt;issue&lt;/a&gt; for the &lt;a href="https://github.com/tarasglek/chatcraft.org"&gt;Chatcraft&lt;/a&gt; project. As I explained, my plan was to use the &lt;code&gt;Strategy Pattern&lt;/code&gt; for solving this issue. I created a response handler interface:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ResponseHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;handleResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I created different response handlers:&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;class&lt;/span&gt; &lt;span class="nc"&gt;NonStreamingResponseHandler&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ResponseHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;handleResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ChatCompletion&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&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;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;functionArgs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseOpenAIResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handleOpenAIResponse&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;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;functionArgs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StreamingResponseHandler&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ResponseHandler&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;handleResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;streamResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;streamChunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;streamResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseOpenAIChunkResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;streamChunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;streamOpenAIResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionArgs&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsedData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chunkContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&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;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;handleOpenAIResponse&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that I had a function to create the correct response handler based on the &lt;code&gt;streaming&lt;/code&gt; flag:&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="nf"&gt;createResponseHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;streaming&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;ResponseHandler&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;streaming&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StreamingResponseHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NonStreamingResponseHandler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;As it can be seen from the code I provided above, my plan was to use the class component pattern. However, the code base that I am contributing to uses functional components. So, I need to change my implementation plan to use the functional component pattern. To do this I plan to just define two separate functions for handling each type of response and use those functions appropriately based on the &lt;code&gt;streaming&lt;/code&gt; flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  To Be Continued
&lt;/h2&gt;

&lt;p&gt;I plan to make another post about my final implementation for this issue.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Chatcraft Enhancement</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Tue, 05 Dec 2023 23:33:55 +0000</pubDate>
      <link>https://dev.to/ahelali/chatcraft-enhancement-4mjm</link>
      <guid>https://dev.to/ahelali/chatcraft-enhancement-4mjm</guid>
      <description>&lt;h2&gt;
  
  
  Issue
&lt;/h2&gt;

&lt;p&gt;This is the first post that I am making about the work I will do on an open source project. The project that I've picked is called &lt;a href="https://github.com/tarasglek/chatcraft.org"&gt;ChatCraft&lt;/a&gt;. It is an open source browser-based companion for coding with large language models. It also provides the option to choose between OpenAI and OpenRouter. The &lt;a href="https://github.com/tarasglek/chatcraft.org/issues/227"&gt;issue&lt;/a&gt; that I've picked to work on is about refactoring the response handling of OpenAI so that the right handler is picked at run-time based on two different response types: &lt;code&gt;streaming response&lt;/code&gt; and &lt;code&gt;non-streaming response&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plan
&lt;/h2&gt;

&lt;p&gt;My plan is to use the &lt;code&gt;Strategy Pattern&lt;/code&gt; because it gives me the flexibility to encapsulate and dynamically change the behaviour of the object at run-time. I think that I will be able to have an abstract response handler with 2 different implementations for each response. One implementation will handle &lt;code&gt;streaming response&lt;/code&gt; and the other will handle &lt;code&gt;non-streaming response&lt;/code&gt;. The way I will handle choosing the response type will be based on a flag that identifies if a response is streaming or non-streaming. After the type of response is decided I will use a &lt;code&gt;Factory Method&lt;/code&gt; to create the object based on the response flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be Continued
&lt;/h2&gt;

&lt;p&gt;I will be posting more as I progress towards solving this issue, so keep an eye out for future updates.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Server-side Pagination</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Mon, 04 Dec 2023 02:27:47 +0000</pubDate>
      <link>https://dev.to/ahelali/server-side-pagination-2pa</link>
      <guid>https://dev.to/ahelali/server-side-pagination-2pa</guid>
      <description>&lt;h2&gt;
  
  
  Pagination Feature
&lt;/h2&gt;

&lt;p&gt;I've been trying to work more on implementing back-end functionalities. When I was searching Github to find an issue related to back-end functionality, I came across this &lt;a href="https://github.com/markjamesm/Sprocket/issues/5"&gt;issue&lt;/a&gt; that grabbed my attention. The issue was about implementing pagination for 2 api endpoints. Pagination is the functionality to divide up and organize the data in separate sequential pages. I was interested in working on this issue because my only experience implementing a pagination feature was done on the front-end side of a web application.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;The setup to work on this project was straightforward. I forked and cloned the project. Then, I had to update my .NET SDK from version 6 to 7, and to update my Visual Studio 2022 to be able to build and run the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changes
&lt;/h3&gt;

&lt;p&gt;My main concern when implementing the pagination feature was to choose the right strategy with the most flexibility for future changes. I chose to add my implementation to the ListPosts() function for the GET posts api and the ListPages() for the GET pages api. I added 2 int parameters to each of these functions that handled the number of items for each page and the number of pages. The parameters allow for flexibility on how many items can be included for each page but they also had default values. Then I used Arithmetic calculations, Skip() and Take() functions, based on the provided values in the parameters to check which items to include and skip from the retrieved data, mapped the data and returned the results. The implementation for both functions can be found below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PagesDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ListPages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pageNum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pageSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;skipItem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pageNum&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pagesFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skipItem&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pagesDto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PagesDto&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;pagesFromDb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pageDto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PageDto&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Author&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="n"&gt;pagesDto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pageDto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pagesDto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PostsDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ListPosts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;postNumber&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;postSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;skipItem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;postNumber&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;postSize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;postsFromDb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;skipItem&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;postSize&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;postsDto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PostsDto&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;postsFromDb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;postDto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PostDto&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Author&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Title&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="n"&gt;postsDto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;postDto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;postsDto&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;After I made my changes, I committed them, and made a &lt;a href="https://github.com/markjamesm/Sprocket/pull/6"&gt;PR&lt;/a&gt; to be reviewed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Even though I had experience with implementing pagination functionality before, it was still interesting to implement the same concept I had used on front-end but for the back-end this time. I think that if I want to implement a pagination functionality in the future, I will take the best of both worlds, and have a mixed implementation between the back-end and the front-end, because I believe it will offer the most flexibility. But, choosing an implementation strategy should be fluid and dependent on what is needed for the overall goal of the program. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Class Component vs Functional Component</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Mon, 04 Dec 2023 01:43:44 +0000</pubDate>
      <link>https://dev.to/ahelali/class-component-vs-functional-component-p44</link>
      <guid>https://dev.to/ahelali/class-component-vs-functional-component-p44</guid>
      <description>&lt;h2&gt;
  
  
  Mattermost
&lt;/h2&gt;

&lt;p&gt;I recently contributed to the &lt;a href="https://github.com/mattermost/mattermost"&gt;Mattermost&lt;/a&gt; project. Mattermost is an open source platform for collaboration across the software development life cycle, and it is written in React and Go. I chose this project because I wanted to work on a big React project with lots of contributors.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Issue
&lt;/h2&gt;

&lt;p&gt;The issue I chose was about converting a class component to a functional component in React without changing its core functionality, and updating the relevant test cases to reflect the conversion. The issue can be found &lt;a href="https://github.com/mattermost/mattermost/issues/25600"&gt;here&lt;/a&gt;. The reason that they wanted to change their components from class to functional was based on React's recommendation and also functional components look to be cleaner, simpler, easier to write and maintain, and there is more support for them through the use of Hooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Process
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;The most challenging part of the process for me was setting up the development environment. First, I had to install WSL on my machine which was done through the command &lt;code&gt;wsl --install&lt;/code&gt; in Powershell. Then, I needed to install Docker Desktop to run the application. I followed the instructions from this &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers#install-docker-desktop"&gt;link&lt;/a&gt; to install Docker Desktop, however I was getting errors running Docker Desktop and Ubuntu. After doing some research I realized that I had to enable virtualization in bios and enable WSL integration for Docker Desktop. I followed the instructions from this &lt;a href="https://support.bluestacks.com/hc/en-us/articles/360058102252-How-to-enable-Virtualization-VT-on-Windows-10-for-BlueStacks-5"&gt;link&lt;/a&gt; to enable virtualization on my machine and the picture below shows where to enable WSL integration for Docker Desktop &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vvCzIelb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ev3km87gm1mlg5knwenf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vvCzIelb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ev3km87gm1mlg5knwenf.png" alt="Image description" width="800" height="419"&gt;&lt;/a&gt;&lt;br&gt;
Afterwards, I installed Go in my WSL environment, increased the number of available file descriptors by using the command &lt;code&gt;ulimit -n 8096&lt;/code&gt;, installed "libpng" in the WSL, forked and cloned the project, installed NVM and used &lt;code&gt;nvm install&lt;/code&gt; to install the correct version of Node.js for the Mattermost web app. After this I was able to run the server and the webapp.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changes
&lt;/h3&gt;

&lt;p&gt;First, I had to do a quick review on my React knowledge and the implementation of class components vs functional components, then I familiarized myself with the Jest testing framework. After that I implemented the conversion and updated the test file associated with that component. The changes that I made can be found in the screenshots below:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EeMgpBSs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ucqq1ff4ksdi34uxg6p6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EeMgpBSs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ucqq1ff4ksdi34uxg6p6.png" alt="Image description" width="800" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EsFlrHWf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wol6h2bu9uxrggl7tfuj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EsFlrHWf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wol6h2bu9uxrggl7tfuj.png" alt="Image description" width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
Finally, I completed the Mattermost's CLA, committed my changes, and created a &lt;a href="https://github.com/mattermost/mattermost/pull/25614"&gt;PR&lt;/a&gt; to be reviewed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Like I said the most challenging part for me was setting up the development environment, since I have never worked with WSL and Docker before. I learned how to set up WSL on my machine, use Docker Desktop for containerized applications, and work with Jest framework. This was also a nice review on my React knowledge, which was very needed since I have been focused on working with C# lately.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Release Time</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Sat, 25 Nov 2023 04:22:51 +0000</pubDate>
      <link>https://dev.to/ahelali/release-time-53bl</link>
      <guid>https://dev.to/ahelali/release-time-53bl</guid>
      <description>&lt;h2&gt;
  
  
  Release 1.0.1
&lt;/h2&gt;

&lt;p&gt;Today, I was able to package and publish my first &lt;a href="https://www.nuget.org/packages/Amir.Text2StaticHtml#versions-body-tab"&gt;NuGet package&lt;/a&gt;. Since my project used the .Net framework, I chose &lt;a href="https://www.nuget.org/"&gt;NuGet&lt;/a&gt; as my package registry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Packaging Process
&lt;/h2&gt;

&lt;p&gt;The process for packaging my project was very easy and straightforward. I found a great video from the .Net YouTube channel that helped me with this. The video can be found &lt;a href="https://www.youtube.com/watch?v=bCoVexnomuk"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps Using Visual Studio&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the project properties from the project menu
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yRJ7EqHl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3a7ah7o0l8llyh9ynvsc.png" alt="Image description" width="373" height="519"&gt;
&lt;/li&gt;
&lt;li&gt;Fill in the details for the package like: Package ID, Title, Authors, Package Version, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bTArGx4n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ndh2k6utbxeppjspy6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bTArGx4n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ndh2k6utbxeppjspy6c.png" alt="Image description" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After the details are filled in, select Pack  from the Build menu.&lt;/li&gt;
&lt;li&gt;A new .nupkg will file will be created under bin/debug folder of the project (This is a default output folder when packing a project, a custom folder can be selected in the previous step).&lt;/li&gt;
&lt;li&gt;Ready to be released.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Publishing Process
&lt;/h2&gt;

&lt;p&gt;The publishing process was very straightforward as well. The steps are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign in to Nuget.org with a Microsoft account.&lt;/li&gt;
&lt;li&gt;Select upload package from the menu.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tRFPlg2j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/25qc4a7u56p1zu2wi9bz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tRFPlg2j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/25qc4a7u56p1zu2wi9bz.png" alt="Image description" width="176" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload the newly created .nupkg.&lt;/li&gt;
&lt;li&gt;Wait for the review to be finished.&lt;/li&gt;
&lt;li&gt;The package is published and ready to be used.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;In order to test out that users were able to use my package, I asked one of my developer friends to test it out for me. Since this is a NuGet package we were not able to run it from the command line. But, he was able to install the package from the NuGet package manager in Visual Studio and add it as a dependency to a test project he had created. From the test project he was able to run the converter and test out all the functionalities that I had implemented.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RwmsDo-y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/78dqyfy1004b9zwphdgh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RwmsDo-y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/78dqyfy1004b9zwphdgh.png" alt="Image description" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Alteration
&lt;/h2&gt;

&lt;p&gt;Luckily I didn't have to make big changes to my code base. I simply added a new public class called "Converter" which was in charge of running the program, so that it'll be accessible when users add the package to their project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package Installation and Usage
&lt;/h2&gt;

&lt;p&gt;This package can be installed from the NuGet package manager by searching for "Amir.Txt2StaticHtml"&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8lhYl4RH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2uetq0awwr5n0b14u9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8lhYl4RH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2uetq0awwr5n0b14u9l.png" alt="Image description" width="800" height="256"&gt;&lt;/a&gt;&lt;br&gt;
Or by going to this &lt;a href="https://www.nuget.org/packages/Amir.Text2StaticHtml#versions-body-tab"&gt;page&lt;/a&gt; and using any of the commands provided. After the package is added to the project simply run the Converter.Run(string[] args) function from the Text2StaticHtml namespace with the valid arguments that can be found in the Readme.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Github Actions &amp; CI</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Sat, 18 Nov 2023 03:41:33 +0000</pubDate>
      <link>https://dev.to/ahelali/github-actions-ci-167f</link>
      <guid>https://dev.to/ahelali/github-actions-ci-167f</guid>
      <description>&lt;h2&gt;
  
  
  CI Workflow
&lt;/h2&gt;

&lt;p&gt;This week I worked on adding a CI workflow to my project through Github actions. The set up was easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I selected a new workflow from the "Actions" section in my repo:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GBskNsB7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2qlvhpqibasirtqd8h1.png" alt="Image description" width="800" height="85"&gt;
&lt;/li&gt;
&lt;li&gt;Searched for and selected the .NET workflow:
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WSDM-faj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j0g49t1oyjhquipid450.png" alt="Image description" width="800" height="415"&gt;
&lt;/li&gt;
&lt;li&gt;I edited the template YAML file to work with my project files:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This workflow will build a .NET project&lt;/span&gt;
&lt;span class="c1"&gt;# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.NET&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;windows-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup .NET&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-dotnet@v3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;dotnet-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;6.0.x&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Restore dependencies&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet restore ./Text2StaticHtml/Text2StaticHtml.sln&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet build ./Text2StaticHtml/Text2StaticHtml.sln --no-restore&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet test ./Text2StaticHtml/Text2StaticHtmlNunitTest/Text2StaticHtmlNunitTest.csproj --no-build --verbosity normal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Committed the YAML file to my repo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing CI Workflow
&lt;/h2&gt;

&lt;p&gt;After adding the CI workflow, I added new test cases for my project to make sure that the workflow got triggered on push and pull request. Then, I made a faulty logic change to intentionally fail a test during the workflow and fixed the faulty logic after I saw that the CI action failed as a result of the faulty logic. &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m1wHjZZx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phmbmrr1qkecgadbxf4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m1wHjZZx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phmbmrr1qkecgadbxf4a.png" alt="Image description" width="359" height="214"&gt;&lt;/a&gt;&lt;br&gt;
So, after I was satisfied that the workflow worked, I merged the changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding To a Friend's Project
&lt;/h2&gt;

&lt;p&gt;I also added a new test case to my friend's project to make sure that his CI workflow worked as well. Since, his project is written in Python he is using Pytest as a testing framework. Because his testing setup is similar to mine, adding a new test case was very simple. I implemented a new test case to check for non-existent file inputs after I asked my friend if there was a specific test case that he wanted me to add to improve his test coverage. The PR for the changes I made can be found &lt;a href="https://github.com/Namatuzio/tiller/pull/24"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;I learned how to setup a CI workflow through Github actions. I can see why a CI workflow is so important, it allows for the automatic building and testing of the project whenever changes are made. I will definitely add CI workflows to my future projects to make my life easier specially with automatic testing.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Late Hacktoberfest Part V</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Sun, 12 Nov 2023 19:08:35 +0000</pubDate>
      <link>https://dev.to/ahelali/late-hacktoberfest-part-v-3e64</link>
      <guid>https://dev.to/ahelali/late-hacktoberfest-part-v-3e64</guid>
      <description>&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;I made 4 contributions to open source projects during my "Late Hacktoberfest" series. My contributions covered a variety of different areas like: creating documentation for repositories, providing efficiency improvements to a codes base, backe-end implementation, and rekindling my old C++ knowledge. Here are the infomration for all the contributions that I made:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Part l &lt;a href="https://dev.to/ahelali/late-hacktoberfest-part-l-1dbd"&gt;post&lt;/a&gt;, the &lt;a href="https://github.com/Webwiznitr/Hacktoberfest-Tulip/issues/9"&gt;issue&lt;/a&gt;, and the &lt;a href="https://github.com/Webwiznitr/Hacktoberfest-Tulip/pull/15"&gt;PR&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 2 &lt;a href="https://dev.to/ahelali/late-hacktoberfest-part-ll-5a0o"&gt;post&lt;/a&gt;, the &lt;a href="https://github.com/dmitry-ivashenko/StatefulUI/issues/4"&gt;issue&lt;/a&gt;, and the &lt;a href="https://github.com/dmitry-ivashenko/StatefulUI/pull/9"&gt;PR&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 3 &lt;a href="https://dev.to/ahelali/late-hacktoberfest-part-lll-dhc"&gt;post&lt;/a&gt;, the &lt;a href="https://github.com/NikolaBV/Console-Spendings-Calculator/issues/33"&gt;issue&lt;/a&gt;, and the &lt;a href="https://github.com/NikolaBV/Console-Spendings-Calculator/pull/41"&gt;PR&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 4 &lt;a href="https://dev.to/ahelali/late-hacktoberfest-part-lv-cbj"&gt;post&lt;/a&gt;, the &lt;a href="https://github.com/TechStarHub/quotes/issues/2"&gt;issue&lt;/a&gt;, and the &lt;a href="https://github.com/TechStarHub/quotes/pull/4"&gt;PR&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most challenging part of this experience was finding the right issues to work on. But, thankfully I was able to find things to work on by narrowing my focus and looking for things I wanted to learn and improve on.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;I covered a variety of different areas with my contributions. My first contribution, helped me understand the value of CONTRIBUTING documentation and how to create one for repositories, and I learned about CODE_OF_CONDUCT documentation for open source repos. My second contribution, added more tools to my C# tool set and and improved my understanding about using a String vs StringBuilder. My third contribution, rekindled my sleeping C++ knowledge and it was a great review on how to use that programming language again. And my fourth contribution, was a good review on back-end implementation and it also thought me about using custom PR template forms. Overall, I am happy with my experience and it helped me take my first steps in getting involved with open source communities. I am walking away from this experience as a more knowledgeable developer and more excited to continue contributing to open source projects. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Late Hacktoberfest Part lV</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Sun, 12 Nov 2023 18:35:23 +0000</pubDate>
      <link>https://dev.to/ahelali/late-hacktoberfest-part-lv-cbj</link>
      <guid>https://dev.to/ahelali/late-hacktoberfest-part-lv-cbj</guid>
      <description>&lt;h2&gt;
  
  
  Final Contribution
&lt;/h2&gt;

&lt;p&gt;This is a post about my fourth and final contribution for this series. I am happy that I reached the goal of 4 contributions at the end. For my final contribution I wanted to work on a web application. First, I chose an issue that was about creating code syntax highlighting for a code translator application, when I started to work on this project I was having a lot of issues trying to get it to work because of the libraries I was trying to use and since I had spent a couple of days trying to get it to work and did not have enough time, I had to move on and choose a simpler web app issue to work on. But, I plan on going back to that project to keep working on it. So, I chose this &lt;a href="https://github.com/TechStarHub/quotes/issues/2"&gt;issue&lt;/a&gt;. For this issue, the project owner wanted to implement a back-end functionality for his web application that was in charge of getting and sending a random quote from a data set and responding to the route associated with it. So, for the fourth time I reached out to be assigned the issue and started to work on it after I forked the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;The implementation for this issue was easy. I created a function that located and read the json data file filled with quotes and I used "fs" and "path" modules to achieve that. After I read the file I parsed the json data and used the Math library to get a random index, then returned a random quote out of all the parsed quotes based on the random index that I had generated. Afterwards, I set up the app.get() method with the correct route for it, called the function I had created to retrieve a random quote inside it and returned it as a json response. I tested everything and made sure that everytime the route was called a new random quote was generated. After I was satisfied that everything was working and I did not break anything I committed my changes and created a &lt;a href="https://github.com/TechStarHub/quotes/pull/4"&gt;PR&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Even though I didn't get to fix the original issue that I had picked for my final contribution due to time constraints, I still plan on going back and working on it on my own time, because it piqued my interest. As for the issue I worked on, it was a nice review on express and back-end implementation. A new thing I learned though was not code related, it was Github related. When I was submitting my PR I saw that the project owner had set up their own PR form as a template, which was very interesting. This was the first time I had encountered a custom PR template when submitting one. I will consider using a custom PR template for my own projects, since it allows for more customization and organization of the PR details.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Late Hacktoberfest Part lll</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Sun, 12 Nov 2023 17:51:43 +0000</pubDate>
      <link>https://dev.to/ahelali/late-hacktoberfest-part-lll-dhc</link>
      <guid>https://dev.to/ahelali/late-hacktoberfest-part-lll-dhc</guid>
      <description>&lt;h2&gt;
  
  
  Third Contribution
&lt;/h2&gt;

&lt;p&gt;C++ was the first coding language I learned and it has been some time since the last time I used it for any of my projects. So, for my third contribution I decided to contribute to a C++ project just to see if I am still capable of utilizing the language and the tools it offers. I searched for a C++ issue on Github and decided to work on this &lt;a href="https://github.com/NikolaBV/Console-Spendings-Calculator/issues/33"&gt;issue&lt;/a&gt;. The project owner wanted to create a functionality for his expenditure tracking console application that went though a spendings csv file for a day and calculated the total amount spent for that day. So I reached out to the owner to assign me the issue and began to work after I was assigned to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;I forked the the repository, created a new branch for the issue and started to work on it. For the implementation I decided to create 3 different functions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A function that was in charge of reading a CSV file and retrieving the data in it as a vector type. This function took a reference to a file path as a parameter and returned a vector of data from the file. The screenshot of the function can be found below: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BWFIvy3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8vhbpw81brbvufp1kzx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BWFIvy3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8vhbpw81brbvufp1kzx.png" alt="Image description" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A function that was in charge of going through the data returned from the previous function and took a reference to that data and a column name reference as parameters. This function went through the vector of data and looked for the index of a specific column based on its name. After finding it's index it went through all the values associated with that column based on the index found, saved all the values in a vector and returned them. This screenshot shows this function: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CDPZ8KRa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jj7cxwj8h2jc38bxj5iw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CDPZ8KRa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jj7cxwj8h2jc38bxj5iw.png" alt="Image description" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A function that took a reference of all the values returned from the previous function and calculated the sum of all of them. Since I have used vectors to store all my data, I decided to use the Algorithm library and utilize transform() and accumulate() functions from it. I used transform and lambda expression to change the type of the values from string to double and used accumulate to get the sum of all the double values. This screenshot shows the implementation: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lj4ge1fP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3yfvbxwhaganjoy3grvv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lj4ge1fP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3yfvbxwhaganjoy3grvv.png" alt="Image description" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After I implemented all the functions and tested them out to make sure everything worked. I committed my changes and created a &lt;a href="https://github.com/NikolaBV/Console-Spendings-Calculator/pull/41"&gt;PR&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;I learned that I can still code in C++ even though it has been a few years since the last time I used it. I had to go over the documentation for the algorithm library again to review how transform() and accumulate() functions worked. So, overall this was a nice review on a language I haven't used in a long time and it rekindled some old knowledge for me.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>NUnit Testing</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Sun, 12 Nov 2023 02:16:29 +0000</pubDate>
      <link>https://dev.to/ahelali/nunit-testing-5a18</link>
      <guid>https://dev.to/ahelali/nunit-testing-5a18</guid>
      <description>&lt;h2&gt;
  
  
  Testing Framework
&lt;/h2&gt;

&lt;p&gt;This week I added a testing framework to my text to html coverter project. I decided to go with &lt;a href="https://nunit.org/"&gt;NUnit&lt;/a&gt;. NUnit initially ported from JUnit and it is an open source unit-testing framework for all .Net languages. I decided to go with this framework because I use C# for my project and NUnit is integrated with Visual Studio and Visual Studio Code which makes it easily accessible for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;The setup was very easy. It was done by simply adding the NUnit Test Project to my solution, which can be seen in the screen shots below: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HKoCZGEM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7dxurdq0bi01q0j4a1dw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HKoCZGEM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7dxurdq0bi01q0j4a1dw.png" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2yLNiFY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgn95kdtisiyoivhpzof.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2yLNiFY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgn95kdtisiyoivhpzof.png" alt="Image description" width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the framework was added, I began to familiarize myself with the steps required to create tests for my program. I learned about the Assert class to check the results of my test actions, the Setup() method to call functions before each test function is called and TearDown() method to call functions after each test function is called, which I used to clean up what was done in Setup(). I also learned that each test function can be divided into 3 parts to make things organized, which are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arrange:&lt;/strong&gt; This is where I prepared variables that I was going to pass to the function I was testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act:&lt;/strong&gt; This is where I called the function I was testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assert:&lt;/strong&gt; This is where I mostly used Assert.IsTrue() and Assert.DoesNotThrow() functions to decide if the function call passed or failed depending on its objective.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing &amp;amp; Results
&lt;/h2&gt;

&lt;p&gt;To begin I started with the most basic function in my program which handles directory creation based on a path parameter. I tested it with a valid directory string and an empty string. The valid directory string test passed and the empty string test failed. So, I had to go and add a try-catch block to that function so that if an empty string was passed as an argument it'd handle the error properly. Then, I decided to add test cases for the core of my program which was in charge of converting a text or a markdown file to html. I wrote around 15 test cases for it with different scenarios like: checking if an html file was created after converting from text/markdown, checking the content of the converted html file to make sure paragraphs, language, horizontal rule, headings, links, and style-sheet were correctly included based on the input files. All the tests for the core of the program passed except for 1, which was converting a "#" markdown identifier to h1 html tag. The issue was that after converting the Heading1 from markdown to h1 in html, the text for the h1 was being repeated in the body. So, I made changes to my code-base to address this issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;This was my first time using a testing framework, and I learned about the value that testing provides, specially when there is a big project with contributors, and a code base that is changing all the time. I learned that when creating a test function I can divide up the logic into: Arrange, Act, and Assert sections to make it easier. Now that I understand how helpful testing can be, I will continue to use it for my projects.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Late Hacktoberfest Part ll</title>
      <dc:creator>Amir Helali</dc:creator>
      <pubDate>Sun, 05 Nov 2023 03:29:48 +0000</pubDate>
      <link>https://dev.to/ahelali/late-hacktoberfest-part-ll-5a0o</link>
      <guid>https://dev.to/ahelali/late-hacktoberfest-part-ll-5a0o</guid>
      <description>&lt;h2&gt;
  
  
  Second Contribution
&lt;/h2&gt;

&lt;p&gt;This is the second post in my multi-part Late Hacktober series. This post is about my second contribution to an open source project during the 2023 Hacktoberfest. Lately, I've been focused on learning and improving my C#. So, I wanted to work on a project using C# and something that was connected to game engines. Luckily I found a "good first issue" &lt;a href="https://github.com/dmitry-ivashenko/StatefulUI/issues/4"&gt;here&lt;/a&gt;, which is about using StringBuilder class instead of String.&lt;/p&gt;

&lt;h2&gt;
  
  
  String vs Stringbuilder
&lt;/h2&gt;

&lt;p&gt;One of the project members had made the observation that one of the custom classes in the code base which was in charge of code generation was using the String class with += operators, and string interpolation, for string concatenation. He recommended that it is more efficient to use a StringBuilder class instead of using String, because the StringBuilder is a mutable item compared to the immutable String. This was interesting to me because first of all, I had never used the StringBuilder class and it was an opportunity to learn something new, and secondly, because it made sense to me that if the string value is not fixed and it will be constantly changing, to use a mutable class in order to avoid memory duplication. So, I went over the StringBuilder &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder?view=net-7.0"&gt;documentation&lt;/a&gt; to understand how it works and what methods I can use to fix this issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working on the Issue
&lt;/h2&gt;

&lt;p&gt;After going over the issue requirements and understanding what and where I needed to implement the fix, I asked the project owner to assign me the issue, which he happily did. Like my first contribution I forked the repo and created a new branch to work on. The implementation was not complicated at all, I just had to replace the String class with the StringBuilder, use StringBuilder methods for string concatenation and override one of the functions with a custom logic. After I implemented the logic, I tested my changes to make sure that it did not break anything in the code base and that it did what was needed. When I was satisfied that everything worked fine, I commited my changes, pushed them, and made a &lt;a href="https://github.com/dmitry-ivashenko/StatefulUI/pull/9/commits"&gt;pull request&lt;/a&gt;. Afterwards, one of the project members reviewed my code, approved it, and the project owner thanked me for my contribution, and merged the code, which will be included in his next release.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;I really liked how appreciative the project owner was of my contribution, even though it was nothing complicated or huge. This made me feel good about contributing to other people's projects, and made me want to do more contributions even after I finish college. It was also a great learning opportunity which allowed me to learn the difference between StringBuilder and String and when to use each one. I will have to go over some of my own C# personal projects and update them, to use StringBuilder instead of String where I have a mutable object.  &lt;/p&gt;

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