<?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>Forem: Chinonso Ikewelugo</title>
    <description>The latest articles on Forem by Chinonso Ikewelugo (@chinonsoike).</description>
    <link>https://forem.com/chinonsoike</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%2F780353%2Feb04fe4c-1c3f-41e7-b6c6-8779b38be9a9.jpeg</url>
      <title>Forem: Chinonso Ikewelugo</title>
      <link>https://forem.com/chinonsoike</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chinonsoike"/>
    <language>en</language>
    <item>
      <title>Understanding Sorting Algorithms (with Examples in Java)</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Fri, 17 Jan 2025 16:36:57 +0000</pubDate>
      <link>https://forem.com/chinonsoike/sorting-algorithms-with-examples-in-java-3ib1</link>
      <guid>https://forem.com/chinonsoike/sorting-algorithms-with-examples-in-java-3ib1</guid>
      <description>&lt;p&gt;Sorting is used to rearrange elements in a list in a specified order. For instance, we might want to sort this list in ascending order:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foklq80cyts2imsxqgpp4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foklq80cyts2imsxqgpp4.png" alt="Image description" width="557" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A sorting algorithm is used to carry out the process of sorting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different Sorting Algorithms
&lt;/h2&gt;

&lt;p&gt;There are several different sorting algorithms in use today. A few we will look at are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/chinonsoike/understanding-bubble-sort-algorithm-with-examples-in-java-3gae"&gt;Bubble Sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/chinonsoike/understanding-selection-sort-algorithm-with-examples-in-java-1nia"&gt;Selection Sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/chinonsoike/understanding-insertion-sort-algorithm-with-examples-in-java-52he"&gt;Insertion Sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/chinonsoike/understanding-merge-sort-algorithm-with-examples-in-java-3m"&gt;Merge Sort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/chinonsoike/understanding-quick-sort-algorithm-with-examples-in-java-335o"&gt;Quick Sort&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Efficiency of Sorting Algorithms
&lt;/h2&gt;

&lt;p&gt;We can determine the efficiency of sorting algorithms by checking their time and space complexities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Time Complexity:
&lt;/h4&gt;

&lt;p&gt;This refers to the amount of time taken for the algorithm its execution with respect to the input. It can be represented in many forms, but the most common is using the &lt;a href="https://web.mit.edu/16.070/www/lecture/big_o.pdf" rel="noopener noreferrer"&gt;Big O notation&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Space Complexity:
&lt;/h4&gt;

&lt;p&gt;This refers to the amount of memory used by the algorithm to complete its execution. It can also be represented using the Big O notation.&lt;/p&gt;

</description>
      <category>sorting</category>
      <category>sortingalgorithms</category>
      <category>java</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Understanding Quick Sort Algorithm (with Examples in Java)</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Fri, 17 Jan 2025 16:15:45 +0000</pubDate>
      <link>https://forem.com/chinonsoike/understanding-quick-sort-algorithm-with-examples-in-java-335o</link>
      <guid>https://forem.com/chinonsoike/understanding-quick-sort-algorithm-with-examples-in-java-335o</guid>
      <description>&lt;p&gt;Quick Sort is a popular sorting algorithm based on the Divide-and-Conquer approach, in which a problem is divided into smaller subproblems and solved individually, then the solutions to the individual subproblems are combined to get the final solution. In Quick Sort, the array is divided by selecting a partition element, the position from which we will divide the array. Before we divide the array, the position of the partition element is rearranged in such a way that it is placed before elements greater than it and after elements smaller than it. The left and right subarrays are further recursively divided in this manner until we reach a case where a subarray contains only one element. At this point, the array is already sorted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working of Quick Sort
&lt;/h2&gt;

&lt;p&gt;Let's say we want to sort this array in ascending order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvf72gz4ya50hpo88dvp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvf72gz4ya50hpo88dvp.png" alt="Image description" width="534" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;We will start by selecting the pivot element. We can select the last element as the pivot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecog4r9t7102k0g8sigd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecog4r9t7102k0g8sigd.png" alt="Image description" width="496" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2
&lt;/h2&gt;

&lt;p&gt;Here we position the pivot element before elements greater than it and after elements smaller than it. To do that we will loop through the array and compare the pivot with all the elements preceding it.&lt;br&gt;
If we find an element greater than the pivot, we create a second pointer for it:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12ajyk9pv2temw8q9eds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12ajyk9pv2temw8q9eds.png" alt="Image description" width="564" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we find an element smaller than the pivot, we swap it with the second pointer:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz10npbchz4kf6cl4xkb6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz10npbchz4kf6cl4xkb6.png" alt="Image description" width="769" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process is repeated to set the next greater element as the second pointer, and swap it with an element smaller than the pivot if found:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwxseed7j1awbu286wfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwxseed7j1awbu286wfs.png" alt="Image description" width="765" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will continue until we get to the end of the array:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cgwcrnhzxudnmzw6ljr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cgwcrnhzxudnmzw6ljr.png" alt="Image description" width="775" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we are done comparing the elements and the elements smaller than the pivot have been moved to the right, we then swap the pivot with the second pointer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhui18c74dejnpatoejbe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhui18c74dejnpatoejbe.png" alt="Image description" width="753" height="419"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3
&lt;/h2&gt;

&lt;p&gt;Here we will divide the array according to the partition index. If we can represent the array as &lt;em&gt;arr[start..end]&lt;/em&gt;, then to divide the array by the partition we can get the left subarray as &lt;em&gt;arr[start..partitionIndex-1]&lt;/em&gt; and the right subarray as &lt;em&gt;arr[partitionIndex+1..end]&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqfsi3sj86t1800jwmns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqfsi3sj86t1800jwmns.png" alt="Image description" width="710" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The subarrays are further divided in this way until each subarray contains only a single element:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8l7f7qhg9cpew3t6c1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8l7f7qhg9cpew3t6c1s.png" alt="Image description" width="582" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, the array is already sorted.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxxokqcjcd1sh370omc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxxokqcjcd1sh370omc6.png" alt="Image description" width="591" height="171"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation of Quick Sort
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class QuickSortTest {
    public static void main(String[] args){
        int[] arr = {8, 6, 2, 3, 9, 4};
        System.out.println("Unsorted array: " + Arrays.toString(arr));
        quickSort(arr, 0, arr.length-1);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    public static int partition(int[] arr, int start, int end){
        // set the last element as the pivot
        int pivot = arr[end];
        // create a pointer for the next greater element
        int secondPointer = start-1;

        // move smaller elements to the left of the pivot
        for (int i = start; i &amp;lt; end; i++) {
            if(arr[i] &amp;lt; pivot){
                secondPointer++;
                int temp = arr[i];
                arr[i] = arr[secondPointer];
                arr[secondPointer] = temp;
            }
        }

        // swap the pivot with the second pointer
        secondPointer++;
        int temp = arr[end];
        arr[end] = arr[secondPointer];
        arr[secondPointer] = temp;

        // return the partition position
        return secondPointer;
    }

    public static void quickSort(int[] arr, int start, int end){
        if(start &amp;lt; end){
            // divide the array into two sub arrays and get the partition index
            int partition = partition(arr, start, end);

            // recursively sort the two sub arrays
            quickSort(arr, start, partition - 1);
            quickSort(arr, partition + 1, end);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's look at the code above.&lt;/p&gt;
&lt;h4&gt;
  
  
  The quickSort Method
&lt;/h4&gt;

&lt;p&gt;In the quickSort method, we first call the partition method to divide the array into two subarrays. We then recursively call quickSort on the left and right subarrays. This process continues until we reach a base condition where all subarrays contain only one element. At this point, the array is already sorted.&lt;/p&gt;
&lt;h4&gt;
  
  
  The partition Method
&lt;/h4&gt;

&lt;p&gt;This is where we divide the into two subarrays. We start by setting pointers for the pivot and the next greater element. Then we loop through the array and move elements smaller than the pivot to the left. After that, we swap the pivot with the second pointer and return the partition position.&lt;/p&gt;

&lt;p&gt;Running the code above will print the following output to the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unsorted array: [8, 6, 2, 3, 9, 4]
Sorted array: [2, 3, 4, 6, 8, 9]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Time Complexity:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Best Case (O(n log n)):
&lt;/h4&gt;

&lt;p&gt;The best case occurs when the pivot divides the array into two nearly equal halves at each step.&lt;/p&gt;

&lt;h4&gt;
  
  
  Average Case (O(n log n)):
&lt;/h4&gt;

&lt;p&gt;In the average case, the pivot divides the array into two unequal parts, but the depth of recursion and the number of comparisons remain proportional to n log n.&lt;/p&gt;

&lt;h4&gt;
  
  
  Worst Case (O(n²)):
&lt;/h4&gt;

&lt;p&gt;The worst case occurs when the pivot consistently divides the array into highly uneven parts (e.g., one part has one element, and the other has n−1 elements). This happens when the pivot is the highest or lowest element, for example when sorting a reverse-order array, with poor pivot selection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Space Complexity (O(log n)):
&lt;/h3&gt;

&lt;p&gt;Quick Sort is generally implemented in-place, requiring no additional arrays.&lt;/p&gt;

</description>
      <category>sorting</category>
      <category>sortingalgorithms</category>
      <category>quicksort</category>
      <category>java</category>
    </item>
    <item>
      <title>Understanding Merge Sort Algorithm (with Examples in Java)</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Fri, 17 Jan 2025 16:15:14 +0000</pubDate>
      <link>https://forem.com/chinonsoike/understanding-merge-sort-algorithm-with-examples-in-java-3m</link>
      <guid>https://forem.com/chinonsoike/understanding-merge-sort-algorithm-with-examples-in-java-3m</guid>
      <description>&lt;p&gt;Merge Sort is one of the most popular sorting algorithms. Many programming languages use either purely Merge Sort or a hybrid algorithm involving Merge Sort for sorting. It is based on the Divide-and-Conquer approach, in which a problem is divided into smaller subproblems and solved individually, then the solutions to the individual subproblems are combined to get the final solution. In Merge Sort, the provided list is recursively divided into two halves, and each half is sorted. Each sorted half is then combined to give a sorted list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working of Merge Sort
&lt;/h2&gt;

&lt;p&gt;Suppose we want to sort an array &lt;em&gt;arr&lt;/em&gt;. Using the Divide-and-Conquer approach and solving recursively:&lt;/p&gt;

&lt;h3&gt;
  
  
  Divide
&lt;/h3&gt;

&lt;p&gt;In the divide step, we will recursively divide into halves until it can no longer be divided; until there is only one element in a subarray. Let us call the 0th index of the array &lt;em&gt;start&lt;/em&gt; and the last index &lt;em&gt;end&lt;/em&gt;. So our array can be represented as &lt;em&gt;arr[start..end]&lt;/em&gt;. Suppose the midpoint of the array is mid, then we can divide the array into two halves, &lt;em&gt;arr[start..mid, mid+1..end]&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conquer
&lt;/h3&gt;

&lt;p&gt;Once the array has been divided until we have two subarrays with only one element in each, each subarray is considered to be sorted. We can now merge two subarrays in sorted order. This process continues until all subarrays have been merged.&lt;/p&gt;

&lt;p&gt;Let's say we want to sort this array in ascending order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqvmusjg4g790tbptyqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqvmusjg4g790tbptyqn.png" alt="Image description" width="731" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an illustration of the process we would go through if we used Merge Sort.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxt6r7lxcq2xnxdsenqko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxt6r7lxcq2xnxdsenqko.png" alt="Image description" width="612" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation of Merge Sort
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MergeSortTest {
    public static void main(String[] args){
        int[] arr = {8, 2, 6, 4, 9, 1};
        System.out.println("Unsorted array: " + Arrays.toString(arr));
        mergeSort(arr, 0, arr.length-1);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    static void merge (int arr[], int start, int mid, int end){
        // create backups of the two subarrays
        int[] left = new int[(mid - start) + 1];
        int[] right = new int[end - mid];

        // copy values into left array
        for(int i = 0; i &amp;lt; left.length; i++){
            left[i] = arr[i+start];
        }

        // copy values into right array
        for(int i = 0; i &amp;lt; right.length; i++){
            right[i] = arr[i+mid+1];
        }

        // maintain pointers to track the current index of the
        // left and right subarrays, and the main array
        int j = start, lIndex = 0, rIndex = 0;

        // set the values from start to end in sorted order, as long
        // as there are still elements in both the left and right subarrays
        while(lIndex &amp;lt; left.length &amp;amp;&amp;amp; rIndex &amp;lt; right.length){
            if(left[lIndex] &amp;lt;= right[rIndex]){
                arr[j] = left[lIndex];
                lIndex++;
            }else {
                arr[j] = right[rIndex];
                rIndex++;
            }

            j++;
        }

        // add leftover values from left subarray if any
        while (lIndex &amp;lt; left.length) {
            arr[j] = left[lIndex];
            lIndex++;
            j++;
        }

        // add leftover values from right subarray if any
        while (rIndex &amp;lt; right.length) {
            arr[j] = right[rIndex];
            rIndex++;
            j++;
        }
    }

    static void mergeSort(int arr[], int start, int end){
        // base condition; will execute only if start is less than end,
        // i.e. there's more than element in the array/subarray
        if(start &amp;lt; end){
            // find the midpoint of the array
            int mid = (start + end) / 2;

            // divide further since we have not reached the base case
            mergeSort(arr, start, mid);
            mergeSort(arr, mid + 1, end);

            // merge the two sorted sections
            merge(arr, start, mid, end);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's look at the code above.&lt;/p&gt;

&lt;h4&gt;
  
  
  The mergeSort Method
&lt;/h4&gt;

&lt;p&gt;In the mergeSort method, we find the midpoint of the array, and recursively call mergeSort to sort the left and right subarrays. The code in mergeSort will run until the base condition is met, that is until the subarray contains only one element.&lt;/p&gt;

&lt;h4&gt;
  
  
  The merge Method
&lt;/h4&gt;

&lt;p&gt;This is the most important part of the merge sort algorithm. In addition to the main array, it takes input indicating the positions of the two sorted subarrays. By knowing &lt;em&gt;start&lt;/em&gt;, &lt;em&gt;mid&lt;/em&gt; and &lt;em&gt;end&lt;/em&gt;, we can represent the left subarray as &lt;em&gt;arr[start..mid]&lt;/em&gt; and the right as &lt;em&gt;arr[mid+1..end]&lt;/em&gt;.&lt;br&gt;
In the merge method, we try to set the values in the main array in sorted order by combining the values from the two subarrays. We start by creating copies of the left and right subarrays. We then create pointers to track the current index of the left and right subarrays, as well as the main array, and loop through the array to set the values from start to end by adding values from the left and right subarrays in sorted order. For instance, the process to merge these two sorted arrays would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubmy99adq5x0lou5r7qe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubmy99adq5x0lou5r7qe.png" alt="Image description" width="346" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running the code above will print the following output to the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unsorted array: [8, 2, 6, 4, 9, 1]
Sorted array: [1, 2, 4, 6, 8, 9]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complexity of Merge Sort
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Time Complexity (O(n log n)):
&lt;/h3&gt;

&lt;p&gt;Merge Sort has a time complexity of O(n log n) in all cases, because it always follows the same divide-and-conquer approach whether the array is already sorted or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Space Complexity (O(n)):
&lt;/h3&gt;

&lt;p&gt;Merge Sort requires additional memory for temporary arrays used during the merge operation.&lt;/p&gt;

</description>
      <category>sorting</category>
      <category>sortingalgorithms</category>
      <category>mergesort</category>
      <category>java</category>
    </item>
    <item>
      <title>Understanding Insertion Sort Algorithm (with Examples in Java)</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Fri, 17 Jan 2025 16:14:38 +0000</pubDate>
      <link>https://forem.com/chinonsoike/understanding-insertion-sort-algorithm-with-examples-in-java-52he</link>
      <guid>https://forem.com/chinonsoike/understanding-insertion-sort-algorithm-with-examples-in-java-52he</guid>
      <description>&lt;p&gt;Insertion sort is a sorting algorithm that works by iteratively inserting each element in an unsorted list into its correct position in a sorted portion of the list. This algorithm is very similar to sorting cards in your hand. We assume that the first card is already sorted, then we take the second card and place it to the right of the sorted card if it is smaller, or to the left if it is bigger. We will continue this process for the remaining cards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working of Insertion Sort
&lt;/h2&gt;

&lt;p&gt;Let's say we want to sort this array in ascending order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqvmusjg4g790tbptyqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqvmusjg4g790tbptyqn.png" alt="Image description" width="731" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  First Iteration
&lt;/h3&gt;

&lt;p&gt;We assume that the first element is already sorted, so we will start the iteration from the second element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqby0ju0wx0zxoo4z42t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvqby0ju0wx0zxoo4z42t.png" alt="Image description" width="442" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will compare the element, 2, with the element in the sorted portion of the array, 8. Since 2 is less than 8, we move 8 to the right and 2 to the left.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3e0t5xvbj0af4n6t1uhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3e0t5xvbj0af4n6t1uhd.png" alt="Image description" width="573" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Second Iteration
&lt;/h3&gt;

&lt;p&gt;We will compare the current element, 6, with the elements in the sorted portion of the array, 2 and 8. Since 6 is less than 8, we move 8 to the right and 6 to the left. 6 is greater than 2 so it is now in its correct position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flamv0m9l3ar00q7oouwe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flamv0m9l3ar00q7oouwe.png" alt="Image description" width="631" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This process is repeated until the entire array is sorted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpuk1xvzf8fc3umv9ed50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpuk1xvzf8fc3umv9ed50.png" alt="Image description" width="475" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpdnc13mxcjifz411s8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpdnc13mxcjifz411s8d.png" alt="Image description" width="473" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foydo45sgpow4riwn6yst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foydo45sgpow4riwn6yst.png" alt="Image description" width="475" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation of Insertion Sort
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class InsertionSortTest {
    public static void main(String[] args) {
        int[] arr = {8, 2, 6, 4, 9, 1};
        System.out.println("Unsorted array: " + Arrays.toString(arr));
        insertionSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    public static void insertionSort(int[] arr){
        // loop through array starting from second element
        for (int i = 1; i &amp;lt; arr.length; i++) {
            int key = arr[i]; // set element at i as key

            // loop backwards through sorted elements to find
            // where to insert the key element
            int j = i-1;

            while (j &amp;gt;= 0 &amp;amp;&amp;amp; key &amp;lt; arr[j]) {
                // move element greater than key to the right
                arr[j+1] = arr[j];
                j--;
            }

            arr[j+1] = key;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, we iterate through the array starting from the second element. Inside the first loop, we set the current element as the key, and then we compare it with each element in the sorted portion of the array by looping backward from i-1 until we find its correct position.&lt;br&gt;
For example, in the second iteration, when i = 2:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz40vkxo1xw11455w9czz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz40vkxo1xw11455w9czz.png" alt="Image description" width="623" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We set the current element as the key:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmvoymwtjup723k0xnpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmvoymwtjup723k0xnpg.png" alt="Image description" width="637" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the while block, we iterate backward through the sorted section of the array. In the first iteration of while loop, j = 1 (i-1). If the current element in the sorted section is greater than the key, we move it to the right by saying arr[j+1] = arr[j]:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hqz1kn05ce2ehwu13rv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hqz1kn05ce2ehwu13rv.png" alt="Image description" width="665" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the second iteration, j = 0. The key 6 is greater than the current element 2, so it does not satisfy the second condition for the while loop and we break out of the while loop.&lt;br&gt;
After breaking out of the loop, we insert the key after the element smaller than it by saying arr[j=1] = key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fha0hlwoxfo2l8sknkvbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fha0hlwoxfo2l8sknkvbj.png" alt="Image description" width="600" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key is now in its correct position and we can move on to the next iteration.&lt;/p&gt;

&lt;p&gt;Running the code above will print the following output to the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unsorted array: [8, 2, 6, 4, 9, 1]
Sorted array: [1, 2, 4, 6, 8, 9]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complexity of Insertion Sort
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Time Complexity:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Best Case (O(n)):
&lt;/h4&gt;

&lt;p&gt;The best case is when the array is already sorted. The algorithm performs n−1 comparisons (one for each element except the first) and no shifts. Therefore, the time complexity is O(n). &lt;/p&gt;

&lt;h4&gt;
  
  
  Average Case (O(n²)):
&lt;/h4&gt;

&lt;p&gt;This occurs when the array's elements are arranged randomly. For each insertion, every element is compared with all previously inserted elements.&lt;/p&gt;

&lt;h4&gt;
  
  
  Worst Case (O(n²)):
&lt;/h4&gt;

&lt;p&gt;The worst case is when the array is sorted in reverse order. Each element must be compared with all previous elements and shifted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Space Complexity O(1):
&lt;/h3&gt;

&lt;p&gt;Insertion Sort is an in-place algorithm and requires no additional memory other than a few variables for looping and temporary storage during shifts.&lt;/p&gt;

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

&lt;p&gt;Insertion Sort has an O(n²) time complexity in the average and worst cases. It is unsuitable when working with large datasets of randomly arranged data due to its high time complexity. Use Insertion Sort when working with small datasets, or when the list is nearly sorted.&lt;/p&gt;

</description>
      <category>sorting</category>
      <category>sortingalgorithms</category>
      <category>insertionsort</category>
      <category>java</category>
    </item>
    <item>
      <title>Understanding Selection Sort Algorithm (with Examples in Java)</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Fri, 17 Jan 2025 16:11:56 +0000</pubDate>
      <link>https://forem.com/chinonsoike/understanding-selection-sort-algorithm-with-examples-in-java-1nia</link>
      <guid>https://forem.com/chinonsoike/understanding-selection-sort-algorithm-with-examples-in-java-1nia</guid>
      <description>&lt;p&gt;In Selection Sort, we iterate through an unsorted list, and on each iteration, the smallest (or largest, if we are sorting in descending order) element is selected and placed at the beginning of the list. This process goes on until all the elements in the list are sorted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working of Selection Sort
&lt;/h2&gt;

&lt;p&gt;Let's say we want to sort this array in ascending order&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyflxdrgs77ovj4wi49z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyflxdrgs77ovj4wi49z.png" alt="Image description" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  First Iteration
&lt;/h3&gt;

&lt;p&gt;The goal of the iteration is to place the smallest element in the unsorted array at the beginning. We start by setting the first element in the unsorted list as the minimum.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dngjb03m9wn2ea4nvxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dngjb03m9wn2ea4nvxg.png" alt="Image description" width="568" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then compare the minimum with the second element, and set the second element as the minimum if it is smaller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjse5b06hcog6229zks6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjse5b06hcog6229zks6w.png" alt="Image description" width="582" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is repeated for the remaining elements and eventually, the smallest element is set as minimum.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblqxk04o44b8hpbz0joy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblqxk04o44b8hpbz0joy.png" alt="Image description" width="577" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then swap the minimum element with the element at the beginning of the unsorted list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xippycniw5iuge9hs0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xippycniw5iuge9hs0b.png" alt="Image description" width="578" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elements that have moved to their correct position are said to be sorted. In subsequent iterations, we will only compare the unsorted elements.&lt;/p&gt;
&lt;h3&gt;
  
  
  Subsequent Iterations
&lt;/h3&gt;

&lt;p&gt;This process is repeated for all iterations until the array is sorted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fag076krtoc50cacw391t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fag076krtoc50cacw391t.png" alt="Image description" width="466" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We iterate through the array n-1 times, where n is the length of the array. That is, since our array has six elements, we iterate through the array only five times. This is because, after the fifth iteration, five elements have been placed in their correct position, therefore the final unsorted element is considered sorted. After all iterations, we will have a sorted array.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation of Selection Sort
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SelectionSortTest {
    public static void main(String[] args) {
        int[] arr = {8, 2, 6, 4, 9, 1};
        System.out.println("Unsorted array: " + Arrays.toString(arr));
        selectionSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    public static void selectionSort(int[] arr){
        int size = arr.length;

        // loop through array size-1 times
        for (int i = 0; i &amp;lt; size-1; i++) {
            int minIndex = i; // set the current index as the minimum

            // loop through the unsorted elements
            for (int j = i+1; j &amp;lt; size; j++) {
                if(arr[j] &amp;lt; arr[minIndex]) minIndex = j;
            }

            // place the minimum element at the current index
            if (minIndex != i){
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running this code will print the following output to the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unsorted array: [8, 2, 6, 4, 9, 1]
Sorted array: [1, 2, 4, 6, 8, 9]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complexity of Selection Sort
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Time Complexity:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Best Case (O(n²)):
&lt;/h4&gt;

&lt;p&gt;Selection Sort always scans the entire unsorted portion of the array to find the minimum element in each pass, whether the array is already sorted or not.&lt;/p&gt;

&lt;h4&gt;
  
  
  Average Case (O(n²)):
&lt;/h4&gt;

&lt;p&gt;Like the best case, the number of comparisons does not depend on the initial ordering.&lt;/p&gt;

&lt;h4&gt;
  
  
  Worst Case (O(n²)):
&lt;/h4&gt;

&lt;p&gt;Similar to the average and best case, the number of comparisons does not depend on the initial ordering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Space Complexity O(1):
&lt;/h3&gt;

&lt;p&gt;Selection Sort is an in-place sorting algorithm, that is, it does not require any extra memory proportional to the size of the input array.&lt;/p&gt;

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

&lt;p&gt;Selection Sort has a time complexity of O(n²) in all cases. It is not suitable to use when working with large datasets due to its high time complexity. Use Selection Sort when working with small datasets, or when you are not concerned with complexity.&lt;/p&gt;

</description>
      <category>sorting</category>
      <category>sortingalgorithms</category>
      <category>selectionsort</category>
      <category>java</category>
    </item>
    <item>
      <title>Understanding Bubble Sort Algorithm (with Examples in Java)</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Fri, 17 Jan 2025 16:09:31 +0000</pubDate>
      <link>https://forem.com/chinonsoike/understanding-bubble-sort-algorithm-with-examples-in-java-3gae</link>
      <guid>https://forem.com/chinonsoike/understanding-bubble-sort-algorithm-with-examples-in-java-3gae</guid>
      <description>&lt;p&gt;Bubble Sort is the simplest sorting algorithm. It works by repeatedly comparing adjacent elements and swapping them if they are not in the correct order. For example, if the sorting order is ascending, adjacent elements are compared, and the greater element is placed on the right. In each iteration, we compare only the unsorted elements, and the largest element is placed at the last position of the unsorted elements in the array.&lt;/p&gt;

&lt;p&gt;The algorithm is aptly named Bubble Sort, because elements move to the right of the array on each iteration in the order specified, much like air bubbles in water rise to the surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working of Bubble Sort
&lt;/h2&gt;

&lt;p&gt;Let's say we want to sort this array in ascending order&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyflxdrgs77ovj4wi49z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyyflxdrgs77ovj4wi49z.png" alt="Image description" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  First Iteration
&lt;/h3&gt;

&lt;p&gt;In the first iteration, we are trying to move the largest element to the end of the array. So, we will repeatedly compare adjacent elements, and swap them if they are out of order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzh5viuj6wftd64o6xsan.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzh5viuj6wftd64o6xsan.png" alt="Image description" width="504" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Elements that have moved to their correct position are said to be sorted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subsequent Iterations
&lt;/h3&gt;

&lt;p&gt;This process is repeated for all iterations until the array is sorted. In each iteration, we only compare the unsorted elements, since the sorted elements are already in the correct order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4cdu6httjjg5ldrgzll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4cdu6httjjg5ldrgzll.png" alt="Image description" width="479" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We iterate through the array &lt;em&gt;n-1&lt;/em&gt; times, where n is the length of the array. That is, since our array has six elements, we iterate through the array only five times. This is because, after the fifth iteration, five elements have been placed in their correct position, therefore the final unsorted element is considered sorted. After all iterations, we will have a sorted array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation of Bubble Sort
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class BubbleSortTest {
    public static void main(String[] args) {
        int[] arr = {8, 2, 6, 4, 9, 1};
        System.out.println("Unsorted array: " + Arrays.toString(arr));
        bubbleSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    public static void bubbleSort(int[] arr) {
        int size = arr.length;

        // loop through array size-1 times
        for (int i = 0; i &amp;lt; size - 1; i++) {
            // loop until end of unsorted elements
            for (int j = 0; j &amp;lt; size - i - 1; j++) {
                // swap left and right elements if left is greater
                if (arr[j] &amp;gt; arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this code will print the following output to the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unsorted array: [8, 2, 6, 4, 9, 1]
Sorted array: [1, 2, 4, 6, 8, 9]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this implementation of Bubble Sort, we will iterate through the array each time even if it is already sorted. We can optimize the code further to stop sorting once the array is already sorted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimized Bubble Sort
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static void bubbleSortOptimised(int[] arr){
        int size = arr.length;

        // loop through array size-1 times
        for (int i = 0; i &amp;lt; size - 1; i++) {
            boolean swapped = false; // track swapping

            // loop until end of unsorted elements
            for (int j = 0; j &amp;lt; size - i - 1; j++) {
                // swap left and right elements if left is greater
                if(arr[j] &amp;gt; arr[j+1]){
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;

                    swapped = true;
                }
            }

            // if there was no swap, then the array is already sorted
            if(!swapped) break;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this implementation, if we are trying to sort an already sorted array, we will iterate only once and stop once no sorting is done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complexity of Bubble Sort
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Time Complexity:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Best Case (O(n)):
&lt;/h4&gt;

&lt;p&gt;The best case is when the input array is already sorted. The algorithm iterates through the array only once to check if it is sorted and performs no swaps.&lt;/p&gt;

&lt;h4&gt;
  
  
  Average Case (O(n²)):
&lt;/h4&gt;

&lt;p&gt;This is when the input array elements are in random order. The algorithm must make multiple iterations and perform swaps to sort the array.&lt;/p&gt;

&lt;h4&gt;
  
  
  Worst Case (O(n²)):
&lt;/h4&gt;

&lt;p&gt;The worst case is when the input array is sorted in reverse order. The algorithm makes &lt;em&gt;n-1&lt;/em&gt; iterations and performs the maximum number of swaps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Space Complexity O(1):
&lt;/h3&gt;

&lt;p&gt;Bubble Sort is an in-place sorting algorithm, that is, it does not require any extra memory proportional to the size of the input array.&lt;/p&gt;

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

&lt;p&gt;Bubble Sort is a simple-to-understand and implement algorithm. However, it is not suitable to use Bubble Sort when working with large datasets due to its high time complexity. Use Bubble Sort when working with small datasets, or when you are not concerned with complexity.&lt;/p&gt;

</description>
      <category>sorting</category>
      <category>bubblesort</category>
      <category>java</category>
    </item>
    <item>
      <title>Logging in .NET 8 with Serilog and Seq</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Sat, 06 Apr 2024 12:56:33 +0000</pubDate>
      <link>https://forem.com/chinonsoike/logging-in-net-8-with-serilog-and-seq-34kn</link>
      <guid>https://forem.com/chinonsoike/logging-in-net-8-with-serilog-and-seq-34kn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When developing locally, we can easily use breakpoints and debugging to inspect our code and see how it behaves. This is not possible when we deploy the application to another environment, say staging or production. When we don't have access to debug locally, we can depend on logs.&lt;br&gt;
Logging is a means by which we keep track of what happens in our applications. We can write logs for informational purposes, or to trace errors in our application.&lt;/p&gt;
&lt;h2&gt;
  
  
  Logging with Serilog
&lt;/h2&gt;

&lt;p&gt;Serilog is a simple-to-use diagnostic logging library for .NET applications. It runs on all recent .NET versions and can be configured to log to files, the console, and other external providers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing and Configuring Serilog
&lt;/h2&gt;

&lt;p&gt;We can install Serilog via the command line or the NuGet package manager.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Serilog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznc4zw8b0q3eo0nwxl6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznc4zw8b0q3eo0nwxl6o.png" alt="Image description" width="800" height="238"&gt;&lt;/a&gt;&lt;br&gt;
Once installed, we can setup Serilog at application startup, typically in the program.cs, using the Serilog.Log static class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Serilog;

Log.Logger = new LoggerConfiguration()
    .CreateLogger();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our configured logger currently does not log to any location. To see our logs we have to configure sinks. Let's see what sinks are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serilog Sinks
&lt;/h2&gt;

&lt;p&gt;Serilog uses sinks to record events to an external representation. When configuring Serilog, we have to specify our desired sinks, if not our events do not get logged anywhere. Serilog sinks are distributed via NuGet. Examples of available sinks include the Console sink, which prints the log data to the console, and the File sink, which writes log events to a file. We can also add these to our application via the command line or NuGet package manager.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepbenevdtuu9u88u8zpf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepbenevdtuu9u88u8zpf.png" alt="Image description" width="800" height="248"&gt;&lt;/a&gt;&lt;br&gt;
We can now configure our logger to write to the desired sinks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("log.txt",
        rollingInterval: RollingInterval.Day)
    .CreateLogger();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WriteTo.Console() specifies that log events should be written to the console.&lt;br&gt;
To use WriteTo.File(), we have to specify the location of the log file. We can also provide some additional parameters like the rollingInterval. Here, we are specifying that a new log file will be created each day.&lt;/p&gt;
&lt;h2&gt;
  
  
  Minimum Level
&lt;/h2&gt;

&lt;p&gt;Serilog provides six log levels:&lt;br&gt;
&lt;strong&gt;Verbose&lt;/strong&gt;: This is the noisiest level, and logs all trace events. This level is not commonly enabled in production environments.&lt;br&gt;
&lt;strong&gt;Debug&lt;/strong&gt;: This level is used to log the application's internal events that are not necessarily observable from outside.&lt;br&gt;
&lt;strong&gt;Information&lt;/strong&gt;: This level is used to log information about the normal application processes.&lt;br&gt;
&lt;strong&gt;Warning&lt;/strong&gt;: This level is used to log warnings about events that are outside of the application's normal behavior.&lt;br&gt;
&lt;strong&gt;Error&lt;/strong&gt;: This is used to log events of broken functionalities in the application. This requires immediate attention.&lt;br&gt;
&lt;strong&gt;Fatal&lt;/strong&gt;: This is the most critical level. It is used for logging events which can cause the application to crash. Fatal events also require immediate attention.&lt;/p&gt;

&lt;p&gt;We can specify the minimum level at which we want to capture events while configuring our logger.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console()
    .WriteTo.File("log.txt",
        rollingInterval: RollingInterval.Day,
        rollOnFileSizeLimit: true)
    .CreateLogger();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If not specified, Serilog uses Information as the minimum level by default.&lt;/p&gt;

&lt;p&gt;We can write log events by using methods of the Log class that match the event level. For example we can write a warning event like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Log.Warning("Unable to load some services");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using the Logger in Application Classes
&lt;/h2&gt;

&lt;p&gt;The easiest way to use the logger in our application classes is via the global Log class. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{ 
    [HttpPost("test-logger")]
    public IActionResult TestLogger()
    {
        Log.Information("This log is from the global Log class");
        return Ok();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run our application and call the test-logger endpoint, we see this in the console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F888dbsnsa0ond7xnga9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F888dbsnsa0ond7xnga9s.png" alt="Image description" width="800" height="37"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another way we can make use of the logger is by injecting it into the class as an ILogger. We first have to configure Serilog as our logging provider. To do this we have to install the Serilog.AspNetCore NuGet package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Serilog.AspNetCore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99rzmplwlhlu5q2uyvcm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99rzmplwlhlu5q2uyvcm.png" alt="Image description" width="800" height="230"&gt;&lt;/a&gt;&lt;br&gt;
NOTE: Serilog.AspNetCore has Serilog and a few sinks as dependencies. So when you install Serilog.AspNetCore, you don't have to install Serilog, Serilog.Sinks.Console and Serilog.Sinks.File.&lt;/p&gt;

&lt;p&gt;After installing the package, we can call UseSerilog() on the Host object of the application builder in our program.cs to configure Serilog as our logging provider and pass in the log object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Host.UseSerilog(Log.Logger);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now make use of the logger in our application class by injecting the ILogger interface in the constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{ 
    private readonly ILogger&amp;lt;TestController&amp;gt; _logger;

    public TestController(ILogger&amp;lt;TestController&amp;gt; logger)
    {
        _logger = logger;
    }

    [HttpPost("test-logger")]
    public IActionResult TestLogger()
    {
        _logger.Information("This log is from the injected ILogger");
        return Ok();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run our application and call the test-logger endpoint, we see this in the console:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvoausgxqxi3cnk1kt2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvoausgxqxi3cnk1kt2z.png" alt="Image description" width="800" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing Logs to Seq
&lt;/h2&gt;

&lt;p&gt;Seq is a self-hosted search and analysis server for structured logs. Events are captured as fully structured JSON data and Seq makes it easy to search and filter through with various parameters. This provides a more efficient way to access and make sense of our logs than writing to files.&lt;br&gt;
Seq can be installed on your local machine or on a Windows or Linux server.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing Seq Locally
&lt;/h2&gt;

&lt;p&gt;You can download Seq .msi from &lt;a href="https://datalust.co/download" rel="noopener noreferrer"&gt;https://datalust.co/download&lt;/a&gt;, and follow the default installation guide to install it on your local machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrf6760u08awf6c83zox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrf6760u08awf6c83zox.png" alt="Image description" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can choose to start the Seq service once the installer has finished copying the files. This will open the Seq Service Administration dialog for the initial setup. You will be prompted to provide the desired location to store Seq's data files and a URL to host Seq's user interface and HTTP API. You can leave these as the defaults. You can also optionally set an administrator username and password.&lt;br&gt;
When you're done with the setup you can open the Seq UI by visiting the default URL, &lt;a href="http://localhost:5341" rel="noopener noreferrer"&gt;http://localhost:5341&lt;/a&gt;, or the one you configured.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcuuak7hpk6v0p2a5pdy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcuuak7hpk6v0p2a5pdy.png" alt="Image description" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After logging in you can access the Seq UI&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fld5f0o4fe90magq15z0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fld5f0o4fe90magq15z0c.png" alt="Image description" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are now ready to configure our logger to write to Seq. To do this we have to install the Seq sink.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Serilog.Sinks.Seq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnpskd0mejm6mnow9cac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnpskd0mejm6mnow9cac.png" alt="Image description" width="800" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our logger configuration we can now write to Seq and provide the Seq URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Seq("http://localhost:5341")
    .CreateLogger();

Log.Information("Starting up application");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us check the Seq UI again to see if our informational log appears:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvhej2f2ahjra552q3b9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvhej2f2ahjra552q3b9.png" alt="Image description" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Logging is an important part of our applications. It can save time in figuring out production issues and also provide necessary information when monitoring. We have seen how to combine Serilog logging with a powerful search and analysis server like Seq.&lt;br&gt;
You can get the sample code for this tutorial &lt;a href="https://github.com/ChinonsoIke/SerilogTutorial" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To learn more about Serilog, you can visit the documentation on their &lt;a href="https://github.com/serilog/serilog/wiki/Getting-Started" rel="noopener noreferrer"&gt;GitHub project&lt;/a&gt;.&lt;br&gt;
To learn more about Seq, you can visit the documentation on their &lt;a href="https://docs.datalust.co/docs/an-overview-of-seq" rel="noopener noreferrer"&gt;website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aspnet</category>
      <category>serilog</category>
      <category>seq</category>
      <category>logging</category>
    </item>
    <item>
      <title>Reading Configuration Values in Your ASP.NET Application</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Sat, 23 Mar 2024 12:00:28 +0000</pubDate>
      <link>https://forem.com/chinonsoike/reading-configuration-values-in-your-aspnet-application-2gl4</link>
      <guid>https://forem.com/chinonsoike/reading-configuration-values-in-your-aspnet-application-2gl4</guid>
      <description>&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Some knowledge of C# and ASP.NET&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When building our applications, we usually have some constants that are either used to handle the application setup, or are part of our application logic. We cannot necessarily hard-code these values where needed, because a change to such a value would require changes in all the files where the value is used. This is not very efficient or neat. The better way is to store these values in a configuration file, such as the appsettings.json file in our ASP.NET application. We can then read the values in our application, and any changes required would be made in just one location, the configuration file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading Configuration Values from appsettings.json
&lt;/h2&gt;

&lt;p&gt;So, how do we read configuration values from our appsettings.json? We will look at two ways we can do this.&lt;/p&gt;

&lt;p&gt;The first is by making use of the configuration object directly. In .NET 5 and below, the configuration object is an instance of ConfigurationRoot, and is present in the Startup.cs by injecting the IConfinguration interface in the constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;

        decimal interestRate = configuration.GetSection("LoanSettings").GetValue&amp;lt;decimal&amp;gt;("InterestRate");
    }

    public IConfiguration Configuration { get; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In .NET 6 and above, the configuration object is an instance of ConfigurationManager, and is a property of the the application builder. So it can be accessed like so in the program.cs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then use a number of methods on the configuration object to read our values. Say we had our appsettings.json structured like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "EnableLoans": true,
  "LoanSettings": {
    "InterestRate": 0.07,
    "DefaultLoanTenure": 6
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can access the InterestRate value by calling GetSection on the configuration object, and chaining GetValue to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decimal interestRate = configuration.GetSection("LoanSettings").GetValue&amp;lt;decimal&amp;gt;("InterestRate");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GetSection retrieves the section with the specified key, and GetValue retrieves the value with the specified key inside that section and converts it to the type specified.&lt;/p&gt;

&lt;p&gt;To access our configuration values outside of the Program.cs or Startup.cs, we add the IConfiguration to the constructor of the classes in which we need the configurations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; public class LoanService
 {
    private readonly IConfiguration _configuration;

    public LoanService(IConfiguration configuration)
    {
        _configuration = configuration;
    }
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now make use of the configuration variable in the same way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decimal interestRate = configuration.GetSection("LoanSettings").GetValue&amp;lt;decimal&amp;gt;("InterestRate");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem with this method is that we're loading our application's entire configuration each time we need it, just to access some specific configurations. So, this is not very performance-friendly.&lt;/p&gt;

&lt;p&gt;A better way would be to fetch only what we need and use it in the class. We can achieve this by creating a model for the section in our appsettings.json, with properties matching the names and types of the keys we have configured. We can then bind the configurations in the section to the model on application startup.&lt;/p&gt;

&lt;p&gt;So, we could have a class matching the LoanSettings section of our appsettings.json like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class LoanSettings
{
    public decimal InterestRate { get; set; }
    public decimal DefaultLoanTenure { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then bind this model to our LoanSettings configuration by calling the Configure method on our service collection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.Configure&amp;lt;LoanSettings&amp;gt;(configuration.GetSection("LoanSettings"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now use the configured instance of LoanSettings like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class LoanService
{
    private readonly IOptions&amp;lt;LoanSettings&amp;gt; _loanSettings;

    public LoanService(IOptions&amp;lt;LoanSettings&amp;gt; loanSettings)
    {
        _loanSettings = loanSettings;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;IOptions is used to retrieve configured instances of LoanSettings. The Value property of the IOptions holds the LoanSettings instance.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;decimal interestRate = _loanSettings.Value.InterestRate;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;We can alternatively inject the LoanSettings directly in our class constructor without wrapping it in IOptions, by adding it as a service after calling Configure on the service collection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.Configure&amp;lt;LoanSettings&amp;gt;(configuration.GetSection("LoanSettings"));
builder.Services.AddScoped(config =&amp;gt; config.GetRequiredService&amp;lt;IOptions&amp;lt;LoanSettings&amp;gt;&amp;gt;().Value);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class LoanService
{
    private readonly LoanSettings _loanSettings;

    public LoanService(LoanSettings loanSettings)
    {
        _loanSettings = loanSettings;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now access the LoanSettings object directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decimal interestRate = _loanSettings.InterestRate;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This is how we access and make use of configuration values in our application safely and efficiently.&lt;/p&gt;

</description>
      <category>aspnet</category>
      <category>appsettings</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Background Job Scheduling in .NET using Hangfire</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Wed, 31 May 2023 08:06:08 +0000</pubDate>
      <link>https://forem.com/chinonsoike/background-job-scheduling-in-net-using-hangfire-3ehm</link>
      <guid>https://forem.com/chinonsoike/background-job-scheduling-in-net-using-hangfire-3ehm</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this article we will look at how to use Hangfire to schedule background jobs in ASP.NET.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Some knowledge of C# and ASP.NET&lt;/li&gt;
&lt;li&gt;SQL Server&lt;/li&gt;
&lt;li&gt;SQL Server Management Studio&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Hangfire?
&lt;/h2&gt;

&lt;p&gt;Hangfire is an opensource framework that helps to efficiently create, process, and manage background tasks in an ASP.NET application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Hangfire
&lt;/h2&gt;

&lt;p&gt;We might have tasks that we want to be performed outside the request processing pipeline, tasks that need to run after some time, or tasks that need to be run at specific intervals and do not require user interaction. For example, sending bulk emails, processing reports, searching for and retrying failed transactions, etc. Hangfire can help us with all these scenarios, and does this efficiently, as we will soon see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hangfire Overview
&lt;/h2&gt;

&lt;p&gt;Broadly speaking, the Hangfire library consists of 3 main components: client, storage and server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ey9o1zejyzn1f8sv8be.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ey9o1zejyzn1f8sv8be.png" alt="Diagram showing Hangfire's components" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;The Hangfire client is used to create the background jobs. You can create various types of background jobs using Hangfire:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fire-and-Forget Jobs:&lt;/strong&gt; These are executed only once almost immediately after creation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delayed Jobs:&lt;/strong&gt; These are tasks that are executed after a set timespan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recurring Jobs:&lt;/strong&gt; These are jobs that are executed at defined intervals, eg hourly, daily, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuations Jobs:&lt;/strong&gt; These are jobs that are chained to other jobs and executed only when the parent job is done executing.&lt;/p&gt;

&lt;p&gt;Background jobs in Hangfire can be created using regular static or instance method invocations. Here's an example of creating a fire-and-forget job using both techniques.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 1)
var client = new BackgroundJobClient();
client.Enqueue(() =&amp;gt; Console.WriteLine("Hello World"));

// 2)
BackgroundJob.Enqueue(() =&amp;gt; Console.WriteLine("Hello World"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;After a job is created using Hangfire, no data is kept in the application's memory. All details relating to the background job's processing, like types, method names, arguments, etc. are serialized and placed into a persistent storage. Persistence helps to keep your background jobs safe in the case of exceptions, application restarts or server reboots. In any of these instances, your background jobs will be retried automatically after restart.&lt;/p&gt;

&lt;p&gt;Different storage backends are supported by Hangfire, eg SQL and Redis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server
&lt;/h3&gt;

&lt;p&gt;Background jobs are processed by the Hangfire server. It does this by querying the storage. The Hangfire server is basically a set of dedicated background threads that listen to the storage for new background jobs, and processes them by deserializing the types, method names and arguments.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hangfire Dashboard
&lt;/h2&gt;

&lt;p&gt;Another good thing about Hangfire is that it provides a graphical interface we can use to visualize and obtain information about our background jobs. We can see information relating to scheduled, succeeded or failed jobs on the Hangfire dashboard. We can also manually retry jobs from the dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfjcip5fpgoogzrbx77k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flfjcip5fpgoogzrbx77k.png" alt="screenshot of the Hangfire dashboard" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo - Hangfire Installation and Configuration
&lt;/h2&gt;

&lt;p&gt;We will create a simple ASP.NET Web Api project and demonstrate how to install and configure Hangfire. We will be using SQL Server as our Hangfire storage.&lt;br&gt;
Our testing scenario will involve creating 3 endpoints to demonstrate 3 of the common jobs we can create using Hangfire.&lt;/p&gt;

&lt;p&gt;a) A user signs up on our ecommerce app and we create a fire-and-forget job to send the user a welcome mail.&lt;br&gt;
b) A user adds an item to their cart and we create a scheduled job to run after 5 minutes and send the user a reminder if the order has not been completed.&lt;br&gt;
c) We call an endpoint to create a recurring job that runs hourly and checks for orders pending delivery.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Create an ASP.NET Web API project&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuv6rhrjkpuyjq9glquge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuv6rhrjkpuyjq9glquge.png" alt="Screenshot of Web API project creation" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Set the project and solution names&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsa97geg626oqluthj3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsa97geg626oqluthj3g.png" alt="Screenshot of Web API project creation" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Select your target framework. I'm going with .NET 5 because I am running VS 19.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ivi6cz54hmv1sf9r1j6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ivi6cz54hmv1sf9r1j6.png" alt="Screenshot of Web API project creation" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Install the following NuGet packages using either the Package Manager Console or the UI window.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hangfire&lt;/li&gt;
&lt;li&gt;Hangfire.SqlServer&lt;/li&gt;
&lt;li&gt;Microsoft.SqlClient&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9r6gdvnw7b7ev6kyxo35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9r6gdvnw7b7ev6kyxo35.png" alt="Screenshot of the Package Manager window on Visual Studio" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: We will also install Swashbuckle.AspNetCore to enable Swagger&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5
&lt;/h3&gt;

&lt;p&gt;Configure Hangfire in Startup.cs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Hangfire;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace HangfireDemo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddHangfire(options =&amp;gt; options.UseSqlServerStorage("Server=.;Initial Catalog=HangfireDB; Integrated Security=true;TrustServerCertificate=True")));
            services.AddHangfireServer();
            services.AddSwaggerGen();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseSwagger();
            app.UseSwaggerUI();

            app.UseHttpsRedirection();

            app.UseHangfireDashboard();

            app.UseRouting();

            app.UseEndpoints(endpoints =&amp;gt;
            {
                endpoints.MapControllers();
            });
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;Here, in the ConfigureServices method we call the AddHangfire extension method and configure it to use SqlServer for storage by calling the UseSqlServerStorage extension method. We also call the AddHangfireServer extension method to enable Hangfire server.&lt;br&gt;
In the Configure method, we add the UseHangfireDashboard middleware to the pipeline to enable the Hangfire dashboard. The default path for the Hangfire dashboard is &lt;a href="https://localhost:port/hangfire" rel="noopener noreferrer"&gt;https://localhost:port/hangfire&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 6
&lt;/h3&gt;

&lt;p&gt;Create the database. Open SSMS and create the database to be used as the Hangfire storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62ptjyznb3frmfsxfifz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62ptjyznb3frmfsxfifz.png" alt="Screenshot database creation on SSMS" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 7
&lt;/h3&gt;

&lt;p&gt;Create HomeController and add endpoints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Hangfire;
using Microsoft.AspNetCore.Mvc;
using System;

namespace HangfireDemo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class HomeController : ControllerBase
    {
        [HttpPost("register")]
        public IActionResult Register()
        {
            // register user

            // create fire-and-forget job to send welcome mail.
            BackgroundJob.Enqueue(() =&amp;gt; SendWelcomeMail());

            return Ok();
        }

        [HttpPost("addtocart")]
        public IActionResult AddToCart()
        {
            // add item to user's cart

            // create scheduled job to send reminder mail if user has not completed order.
            BackgroundJob.Schedule(() =&amp;gt; SendReminder(), TimeSpan.FromMinutes(5));

            return Ok();
        }

        [HttpGet("addrecurringjob")]
        public IActionResult AddRecurringJob()
        {
            RecurringJob.AddOrUpdate("Pending Deliveries Job", () =&amp;gt; CheckPendingDeliveries(), Cron.Hourly);

            return Ok();
        }

        public static void SendWelcomeMail()
        {
            Console.WriteLine("Welcome mail has been sent to user");
        }

        public static void SendReminder()
        {
            bool completed = new Random().Next() % 2 == 0;

            if (completed)
            {
                Console.WriteLine("The user has already completed the order for cart item xxxx");
            }
            else
            {
                Console.WriteLine("A reminder has been sent to user for cart item xxxx");
            }
        }

        public static void CheckPendingDeliveries()
        {
            int number = new Random().Next(1, 10);

            Console.WriteLine($"There are {number} pending deliveries");
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;The BackgroundJob class provides static methods for creating fire-and-forget jobs, delayed jobs and continuation jobs.&lt;br&gt;
The Enqueue method is used to create fire-and-forget jobs, and takes in the method call expression as a parameter. The Schedule method is used to create delayed jobs, and takes in the method call expression and a timespan indicating the delay.&lt;/p&gt;

&lt;p&gt;The RecurringJob class provides static methods for creating and managing recurring jobs.&lt;br&gt;
The AddOrUpdate method adds a new recurring job or updates an existing one. It takes in the job ID, the method call expression and the Cron expression for the interval.&lt;/p&gt;

&lt;p&gt;When we run the application, we see the Swagger index page and our three endpoints. Calling the endpoints will create the different jobs we have set up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbdw6xhqum35b9eudhd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbdw6xhqum35b9eudhd5.png" alt="Screenshot of Swagger index page" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we navigate to the Hangfire dashboard, we can see information about the jobs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7hc0lf9x98kuskrnrai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7hc0lf9x98kuskrnrai.png" alt="Screenshot of Hangfire dashboard" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek3h665my8qngg4a2vx3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek3h665my8qngg4a2vx3.png" alt="Screenshot of Hangfire dashboard" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see, the Hangfire dashboard displays information about running and scheduled jobs, and also their success or failed status.&lt;/p&gt;

&lt;p&gt;If we look at the HangfireDB we created earlier, we can see that a bunch of tables have been generated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fficstst95hfp0viz5i4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fficstst95hfp0viz5i4a.png" alt="Screenshot of Hangfire dashboard" width="682" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article we looked at how to use Hangfire to schedule background jobs in ASP.NET according to our requirements. In a follow up article, I will talk about using Hangfire with a Redis storage.&lt;br&gt;
To learn more about Hangfire, you can visit the &lt;a href="https://www.hangfire.io/" rel="noopener noreferrer"&gt;official website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>hangfire</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>aspdotnet</category>
    </item>
    <item>
      <title>Introduction to Clean Architecture with .NET</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Sat, 12 Nov 2022 12:31:57 +0000</pubDate>
      <link>https://forem.com/chinonsoike/introduction-to-clean-architecture-with-net-5ab4</link>
      <guid>https://forem.com/chinonsoike/introduction-to-clean-architecture-with-net-5ab4</guid>
      <description>&lt;p&gt;In this article, we're going to talk about Clean Architecture and its many benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Knowledge of C# and .NET&lt;/li&gt;
&lt;li&gt;Basic understanding of the Dependency Inversion Principle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get right to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The smallest possible number of projects for an application architecture in .NET is one. Here, the entirety of the application, the business, presentation, and data access logic is contained in a single project, compiled to a single assembly, and deployed as a single unit. This type of all-in-one architecture might serve small applications well, but as applications get bigger this becomes unsustainable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl45xgzxyfeam97hvho07.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl45xgzxyfeam97hvho07.png" alt="All-in-one Project" width="571" height="912"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Folders relating to each aspect of the project can keep growing and get scattered across with no apparent cohesiveness between related folders, for example, user interface logic can reside in different folders (models, views, controllers), same with business and data access logic. Along with this, there is no clear indication of which classes in which folders should depend on which others. This lack of organization at the project level frequently leads to what is called spaghetti code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwq4uv0r191qayazzswyx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwq4uv0r191qayazzswyx.jpg" alt="A plate of spaghetti" width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Layers to the Rescue
&lt;/h2&gt;

&lt;p&gt;To mitigate the issues mentioned above, applications often evolve into multi-project solutions, where each project represents a particular layer of the solution. Layers represent logical separation within the application. They are a way to manage complexity by breaking an application into different parts according to its responsibilities or concerns.&lt;/p&gt;

&lt;p&gt;The most common organization of application logic into layers is shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrmmdtdg5ehabaf4s7uz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffrmmdtdg5ehabaf4s7uz.png" alt="Image of traditional N-layer application" width="299" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Explanation of Terms
&lt;/h2&gt;

&lt;h3&gt;
  
  
  User Interface/ Presentation
&lt;/h3&gt;

&lt;p&gt;This is the entry point of the application. It is the part of the application that the client/user interracts with.&lt;/p&gt;

&lt;h3&gt;
  
  
  Business Logic
&lt;/h3&gt;

&lt;p&gt;This part is where the main implementation of an application is carried out. This part is responsible for solving whatever problem the application has set out to solve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Access Logic
&lt;/h3&gt;

&lt;p&gt;This is the part of the application that provides easy and simplified access to data stored in persistent storage, eg data stored in an SQL database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuation
&lt;/h2&gt;

&lt;p&gt;Using this architecture, user can communicate with the UIL, which in turn communicates with the BLL, which communicates with the DAL. The UIL should not speak to the DAL directly, or implement persistence by any other means. This way, each layer has its own well-defined responsibility.&lt;/p&gt;

&lt;p&gt;However, this traditional layering approach also has a disadvantage, because dependencies seem to flow downward; the UIL depends on the BLL, and the BLL on the DAL. The business logic layer, which usually holds the most important logic of the application, depending on the data access details poses a problem, for example, tesing the BLL can be difficult because we now require a test database. Making changes to your data access details can also result in changes to the BLL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Clean Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uum4sbb6ihdftudw0ad.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uum4sbb6ihdftudw0ad.jpg" alt="Sneaky Tom meme" width="600" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clean architecture puts the business logic at the center of the application. This is achieved mainly by following the Dependency Inversion Principle (DIP). If you're unfamiliar with this topic, you can check out a brief overview &lt;a href="https://www.freecodecamp.org/news/solid-principles-explained-in-plain-english/amp/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead of having the application core (which contains the business logic) depend on data access and other infrastructure details, this dependency is inverted; infrastructure and implementation details depend on the application core. This is achieved by defining abstractions (interfaces) in the Application Core, which will be implemented by types defined in the Infrastructure layer. Below is a diagram depicting a common visualization of Clean Architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14bnz79gxnerr8j0eqzu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14bnz79gxnerr8j0eqzu.png" alt="Clean Architecture Diagram" width="619" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see from the figure above, dependencies in Clean Architecture flow inward, and the Application Core has no dependencies on any other layers. The entities and interfaces are at the very center. Outside this, but still in the Application Core, we have the domain services, which typically implement the interfaces defined in the inner circle.&lt;/p&gt;

&lt;p&gt;The Infrastructure and UI layers both depend on the Application Core, but not necessarily on each other. Since the Application Core doesn’t depend on the Infrastructure, it’s very easy to write automated unit tests for this layer. Also, since the UI layer doesn't have any direct dependency on the Infrastrucure layer, it is also easy to swap out implementations, either for testing purposes or due to changing technical requirements (for example, switching the UI layer from a MVC project to a Web API).&lt;/p&gt;

&lt;h2&gt;
  
  
  Organizing Code in Clean Architecture
&lt;/h2&gt;

&lt;p&gt;Layers in applications that follow Clean Architecture have specific, well-defined responsibilities. As such, certain types belong in each project, and developers can easily find where certain functionality is implemented.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Core
&lt;/h2&gt;

&lt;p&gt;The Application Core contains the main business logic of the application; the entities, interfaces, and the domain services, along with few other types central to the business logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Core Types
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Entities&lt;/li&gt;
&lt;li&gt;Interfaces&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Data Transfer Objects&lt;/li&gt;
&lt;li&gt;Specifications&lt;/li&gt;
&lt;li&gt;Custom Exceptions and Handlers, etc&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Infrastructure
&lt;/h2&gt;

&lt;p&gt;The Infrastructure project typically includes data access implementations. In a project developed using Entity Framework, the Infrastructure layer would also contain the DbContext implementation, and any migration objects that have been created. The Infrastructure layer is also where you would find infrastructure-specific services (eg mailing services). These services would implement interfaces defined in the Application Core&lt;/p&gt;

&lt;h3&gt;
  
  
  Infrastructure Layer Types
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;EF Core DbContext&lt;/li&gt;
&lt;li&gt;Migrations&lt;/li&gt;
&lt;li&gt;Infrastructure-specific services&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  UI/Presentation
&lt;/h2&gt;

&lt;p&gt;This layer is the entry point of the application. It is also in this layer that the application is configured and implementation types are provided for interfaces defined in the Application Core.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI/Presentation Layer Types
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Controllers&lt;/li&gt;
&lt;li&gt;View&lt;/li&gt;
&lt;li&gt;ViewModels&lt;/li&gt;
&lt;li&gt;Custom middlewares/filters&lt;/li&gt;
&lt;li&gt;Program.cs&lt;/li&gt;
&lt;li&gt;Startup.cs&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;This has been a brief overview of Clean Architecture and its benefits. Microsoft has provided a sample ASP.NET Core 6.0 reference application implementing Clean Architecture. You can view it &lt;a href="https://github.com/dotnet-architecture/eShopOnWeb" rel="noopener noreferrer"&gt;here&lt;/a&gt; to get a more practical understanding of this topic.&lt;/p&gt;

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

&lt;p&gt;Microsoft Documentation - &lt;a href="https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures&lt;/a&gt;&lt;br&gt;
EShopOnWeb - &lt;a href="https://github.com/dotnet-architecture/eShopOnWeb" rel="noopener noreferrer"&gt;https://github.com/dotnet-architecture/eShopOnWeb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cleanarchitecture</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>API Authentication using Laravel Sanctum</title>
      <dc:creator>Chinonso Ikewelugo</dc:creator>
      <pubDate>Mon, 10 Jan 2022 06:55:31 +0000</pubDate>
      <link>https://forem.com/chinonsoike/api-authentication-using-laravel-sanctum-1af6</link>
      <guid>https://forem.com/chinonsoike/api-authentication-using-laravel-sanctum-1af6</guid>
      <description>&lt;p&gt;In this tutorial, we’re going look at what the Laravel Sanctum package is and what it does.&lt;br&gt;
Sanctum is a Laravel package which provides a simple means for authenticating your SPAs, mobile apps, and simple token-based APIs.&lt;br&gt;
Let’s get right to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#Step 1&lt;/strong&gt;&lt;br&gt;
We will begin by creating a new Laravel project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;laravel new lara-vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’m using &lt;a href="https://laragon.org/" rel="noopener noreferrer"&gt;Laragon&lt;/a&gt; for my local development, so I can access my project by visiting &lt;a href="http://lara-vue.test" rel="noopener noreferrer"&gt;http://lara-vue.test&lt;/a&gt;. You can access yours according to the configurations of your local server&lt;br&gt;
Next, create your database and edit the contents of the .env file in your app’s root directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_CONNECTION = mysql
DB_HOST = 127.0.0.1
DB_PORT = 3306
DB_DATABASE = YourDBName
DB_USERNAME = YourDBUsername
DB_PASSWORD = YourDBPassoword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;#Step 2&lt;/strong&gt;&lt;br&gt;
We can now install Laravel Sanctum&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require laravel/sanctum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, we will publish the Sanctum configuration and migration files using the vendor:publish Artisan command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will place the configuration file in the config directory of our project.&lt;br&gt;
Next, we run the database migrations. Sanctum will create a database table in which to store API tokens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Migration table created successfully.
...
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (1,081.77ms)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will notice that a personal_access_tokens table has been added to your database. This is where the user tokens will be stored.&lt;/p&gt;

&lt;p&gt;Next, add Sanctum's middleware to your API middleware group in the app/Http/Kernel.php file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'api' =&amp;gt; [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;#Step 3&lt;/strong&gt;&lt;br&gt;
To use tokens to authenticate users, we have to add the HasApiToken trait to the app/models/User model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When making requests using API tokens, the token should be included in the Authorization header as a Bearer token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#Step 4&lt;/strong&gt;&lt;br&gt;
Let us now create our authentication routes in the routes/api.php file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use App\Http\Controllers\AuthController;

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login'])-&amp;gt;name('login');

Route::middleware('auth:sanctum')-&amp;gt;group(function () {
    Route::post('/logout', [AuthController::class, 'logout']);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you noticed, we called AuthController without creating it. Let us create it using this simple command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:controller AuthController
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in our AuthController,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    public function register(Request $request)
    {
        try{
            $attributes= $request-&amp;gt;validate(
                [
                    'name'=&amp;gt;'required|min:3|max:30',
                    'email'=&amp;gt;'required|email|unique:users',
                    'password'=&amp;gt;'required|min:6|max:30',
                ]
            );

            $attributes['password']= bcrypt($attributes['password']);

            $user = User::create($attributes);

            $message= "Account created successfully, welcome aboard.";
            $success= true;
        } catch(Exception $e){
            $success= false;
            $message= $e-&amp;gt;getMessage();
        }


        $response= [
            'success'=&amp;gt;$success,
            'message'=&amp;gt;$message,
        ];

        return response()-&amp;gt;json($response);
    }

    public function login(Request $request)
    {
        $attributes= $request-&amp;gt;validate(
            [
                'email'=&amp;gt;'required|email',
                'password'=&amp;gt;'required',
            ]
        );

        if(!auth()-&amp;gt;attempt($attributes)){
            return response()-&amp;gt;json(
                ['message'=&amp;gt;'These credentials do not match our records'], 401
            );
        }

        $user= auth()-&amp;gt;user();
        $token= $user-&amp;gt;createToken($user-&amp;gt;id)-&amp;gt;plainTextToken;

        $message= "User logged in successfully";
        $success= true;

        $response= [
            'success'=&amp;gt;$success,
            'message'=&amp;gt;$message,
            'data'=&amp;gt;[
                'user'=&amp;gt;$user,
                'token'=&amp;gt;$token,
            ],
        ];     

        return response()-&amp;gt;json($response, 200);
    }


    public function logout()
    {
        Session::flush();
        $success= true;
        $message= 'User logged out successfully';

        $response= [
            'success'=&amp;gt;$success,
            'message'=&amp;gt;$message,
        ];

        return response()-&amp;gt;json($response);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we set up our authentication logic. The register method creates a new user in our app, the login method authenticates users and generates an access token on succesful login, and the logout method removes the user's session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#Step 5&lt;/strong&gt;&lt;br&gt;
All we have left to do is test our implementation. We can do this using &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; or &lt;a href="https://insomnia.rest/" rel="noopener noreferrer"&gt;Insomnia&lt;/a&gt; packages. We'll send requests to our register and login routes.&lt;/p&gt;

&lt;p&gt;If everything works well, we will receive a JSON response similar to this:&lt;br&gt;
Registration Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "success":true,
    "message":"Account created successfully, welcome aboard."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Login Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "success":true,
    "message":"User logged in successfully"
    "data":{
        "user": {
            "id": 1,
            "name": "Emeka Ike",
            "email": "emekaike@test.com",
            "email_verified_at": null,
            "created_at": null,
            "updated_at": null
        },
        "token": "uIuSGRGAblahGHblah..."
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
In this tutorial, we looked at what Laravel Sanctum is and what it does. We covered how to install and setup Sanctum, and how to use it to authenticate and give access to users. This gives us the power to build powerful APIs.&lt;/p&gt;

&lt;p&gt;You can view the source code for this tutorial &lt;a href="https://github.com/ChinonsoIke/Laravel-Sanctum-Tutorial" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I hope you found this helpful, and if you have any questions, just let me know in the comments and I will clarify further.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>sanctum</category>
      <category>api</category>
    </item>
  </channel>
</rss>
