<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Katherine Mykhailyk</title>
    <description>The latest articles on DEV Community by Katherine Mykhailyk (@katerinamykhailyk).</description>
    <link>https://dev.to/katerinamykhailyk</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%2F1071841%2Fc7f8610d-34da-4c38-a290-236efd9ca64d.png</url>
      <title>DEV Community: Katherine Mykhailyk</title>
      <link>https://dev.to/katerinamykhailyk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/katerinamykhailyk"/>
    <language>en</language>
    <item>
      <title>Exploring the Need for Creational (Factory) Design Patterns</title>
      <dc:creator>Katherine Mykhailyk</dc:creator>
      <pubDate>Wed, 17 May 2023 20:54:11 +0000</pubDate>
      <link>https://dev.to/katerinamykhailyk/exploring-the-need-for-creational-factory-design-patterns-3h6d</link>
      <guid>https://dev.to/katerinamykhailyk/exploring-the-need-for-creational-factory-design-patterns-3h6d</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pspfi5kjpzck57q734n.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pspfi5kjpzck57q734n.jpeg" alt="Image description" width="612" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have a strong affinity for design patterns as they provide elegant solutions to common architectural design challenges. &lt;/p&gt;

&lt;p&gt;The definitive resource for design patterns is the &lt;a href="https://www.goodreads.com/book/show/85009.Design_Patterns?from_search=true&amp;amp;from_srp=true&amp;amp;qid=pAuDfmMhHJ&amp;amp;rank=1"&gt;Gang of Four book&lt;/a&gt;, that builds their general classification around the conceptual motivations of the patterns taking into account the specific problems they tackle:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Behavioural patterns&lt;/strong&gt; focus on managing variations in behaviour within a system. They provide solutions for scenarios where different objects or components need to exhibit different behaviours.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For example, suppose you have an application that involves different payment methods, each of which has its own specific behaviour, including authentication, transaction processing, and receipt generation. In this case, one of the behavioural patterns can be employed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Structural patterns&lt;/strong&gt; provide guidelines on how to construct larger structures by organising objects and classes in a manner that ensures flexibility and efficiency.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For example, you have a legacy system that uses a monolithic architecture, where different components are tightly coupled together. Now, you want to introduce a new feature without disrupting the existing system. In this case, you can apply the Adapter structural pattern, which allows you to adapt the new feature to the existing system without modifying its core components. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Creational&lt;/strong&gt; (sometimes, I hear them referred to as Factory patterns or simply Factories) serve a key role in object creation&lt;/em&gt;, although their significance goes beyond that. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Factories&lt;/strong&gt; are objects designed to produce other objects. &lt;/p&gt;

&lt;p&gt;In OOP languages, when the code responsible for using objects is also burdened with their instantiation (which is frequently the case), complexity can arise. Such code becomes responsible for keeping track of multiple aspects, such as which objects to create, which construction parameters are necessary, how to utilise the object after construction, and sometimes even managing object pools. This lack of separation reduces cohesion, which is undesirable, and can lead developers to prematurely choose an instantiation scheme before fully understanding the objects that need to be instantiated.&lt;/p&gt;

&lt;p&gt;Factory patterns address these issues by promoting object cohesion, decoupling, and testability. They contribute to maintaining a flexible design and facilitate problem decomposition into smaller, more manageable components.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When it comes to object creation and management, here is a good rule to follow: and object should either make and / or manage other objects or it should use other objects but it should never do the both. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This division of responsibilities simplifies the tasks for both groups. Moreover, by streamlining the creation and management of objects, it's possible to enhance their management without significantly increasing effort.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I would recommend following these steps:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Step 1&lt;/em&gt; - Define the objects and their relations.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Step 2&lt;/em&gt; - Implement factories for object instantiation and management: write factories that handle the creation of the appropriate objects based on specific situations, as well as managing existing objects if they are shared among different components.&lt;/p&gt;

&lt;p&gt;As you can see, the code generated in Step 1 focuses solely on the behaviour and functionality of the objects without concerning itself with the instantiation details. Similarly, the code in Step 2 concentrates on the instantiation and management of objects, without being burdened by the complexities of their interactions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Separating these concerns leads to increased cohesion in the code. If these aspects were not separated, you would end up with code that deals with both the functionality of the objects and the rules governing their creation and management in different circumstances. By isolating these concerns, each class can focus on either functionality or instantiation, resulting in more modular and cohesive code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's worth mentioning, that this approach provides us with enhanced encapsulation, a highly valued characteristic. It ensures complete separation between the implementing classes and the client code that utilises them. Consequently, I can introduce or remove implementations without requiring any modifications to the client code itself.&lt;/p&gt;

&lt;p&gt;Moreover, this approach greatly facilitates the testing process. The behaviour of the client code remains consistent regardless of the specific set of implementations employed. It is sufficient to test each component individually, as the system will function in a consistent manner regardless of their combinations.&lt;/p&gt;

&lt;p&gt;Other benefits include easier and more cost-effective maintenance in the future. They align with the open-closed principle, allowing for the addition of new code rather than modifying existing code when changes are necessary. This approach effectively reduces the overall maintenance costs.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Please consider this piece of code and think, what could be improved: &lt;/u&gt;&lt;/p&gt;

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

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

&lt;p&gt;At first glance, the provided code appears fine, and I have encountered similar implementations in the past. &lt;u&gt;However, there are a few key aspects that require attention: &lt;/u&gt;&lt;/p&gt;

&lt;p&gt;1) OrderManager class creates instance of Order object (line #14) directly by itself. It would be okay, if only you won't need to do all other stuff: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating the OrderId (line #15) and handling the associated logic internally (line #25)&lt;/li&gt;
&lt;li&gt;Setting the CustomerName (line #16)&lt;/li&gt;
&lt;li&gt;Setting the TotalAmount (line #17)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2) The OrderManager class also performs order management operations: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Saving the order to the database (line #20) and keeping the logic within itself (line #31)&lt;/li&gt;
&lt;li&gt;Sending a confirmation email (line #21) and managing the process internally (line #36)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can observe, this class is responsible for multiple tasks, and it would greatly benefit from being divided into smaller, more understandable components. Since we are discussing creational design patterns, we can utilise one of them to eliminate lines #15-#17 and #25-#29. This modification would align the class more closely with the Single Responsibility Principle. I plan to cover this subject in our future articles.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One more thing, that you need to know is that there is a range of creational patterns exist:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Factory Method&lt;/li&gt;
&lt;li&gt;Abstract Factory&lt;/li&gt;
&lt;li&gt;Singleton&lt;/li&gt;
&lt;li&gt;Prototype&lt;/li&gt;
&lt;li&gt;Builder&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I will begin with the Factory Method, which is remarkably straightforward to comprehend and implement.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In conclusion, the use of creational patterns, provides significant benefits in software development. By separating the object creation process from object usage, factories enable more flexible, modular, and maintainable code. They promote encapsulation, allowing for easy addition or removal of implementations without impacting the client code. Additionally, creational patterns adhere to the open-closed principle, reducing maintenance costs by enabling the addition of new code rather than modifying existing code. Overall, incorporating factories and creational patterns in design and development leads to improved code organisation, testability, and future scalability.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Other examples of this patterns: DbProviderFactory Class&lt;/p&gt;

</description>
      <category>programming</category>
      <category>designpatterns</category>
      <category>oop</category>
      <category>beginners</category>
    </item>
    <item>
      <title>JavaScript Metaprogramming: Part 1 - Unleashing the Potential of the Reflect API</title>
      <dc:creator>Katherine Mykhailyk</dc:creator>
      <pubDate>Tue, 16 May 2023 05:53:25 +0000</pubDate>
      <link>https://dev.to/katerinamykhailyk/javascript-metaprogramming-part-1-unleashing-the-potential-of-the-reflect-api-4lka</link>
      <guid>https://dev.to/katerinamykhailyk/javascript-metaprogramming-part-1-unleashing-the-potential-of-the-reflect-api-4lka</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foq1bb3af1wk5p18t7047.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foq1bb3af1wk5p18t7047.png" alt="Image description" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Metaprogramming" rel="noopener noreferrer"&gt;&lt;em&gt;Metaprogramming&lt;/em&gt;&lt;/a&gt;&lt;/strong&gt; is a programming technique (or approach) which involves treating programs as data, enabling them to be &lt;em&gt;read, generated, analysed, transformed, and even modified&lt;/em&gt; dynamically. It empowers developers to &lt;em&gt;interact&lt;/em&gt; with and &lt;em&gt;manipulate&lt;/em&gt; other programs programmatically. &lt;/p&gt;

&lt;p&gt;Essentially, this concept conveys that metaprogramming enables us to create sophisticated programs with the ability to &lt;em&gt;generate new programs&lt;/em&gt; or &lt;em&gt;comprehend&lt;/em&gt; their &lt;em&gt;own structure&lt;/em&gt;. However, what does this actually mean in practice?&lt;/p&gt;

&lt;p&gt;To begin, it is essential to grasp that metaprogramming encompasses both language capabilities and approaches to writing logic in a metaprogramming style. &lt;/p&gt;

&lt;p&gt;I would like to start my explanation with the aspect that emphasises metaprogramming as the program's &lt;em&gt;self-awareness&lt;/em&gt; and the ability to &lt;em&gt;manipulate itself&lt;/em&gt; at runtime. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Reflective_programming" rel="noopener noreferrer"&gt;Reflection&lt;/a&gt;&lt;/strong&gt; stands out as a significant tool in this context. It's the concept within metaprogramming, which draws parallels to seeing our own reflection in a mirror. In a similar manner, reflection allows us to gain insights into aspects of a program that would otherwise remain hidden. It provides the capability to introspect and access different elements of a program, such as &lt;em&gt;properties, methods, and structure&lt;/em&gt;. This ability to observe and modify a program's internal workings facilitates advanced program analysis and dynamic adaptations.&lt;/p&gt;

&lt;p&gt;At its core, reflection allows an object to introspect its &lt;em&gt;own properties and methods&lt;/em&gt;, enabling &lt;em&gt;self-examination&lt;/em&gt; and potential &lt;em&gt;modification&lt;/em&gt;. In the case of JavaScript, this capability empowers objects to dynamically explore their own structure, accessing and manipulating properties and methods as required.&lt;/p&gt;

&lt;p&gt;In JavaScript, the &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect" rel="noopener noreferrer"&gt;Reflect API&lt;/a&gt;&lt;/strong&gt; serves as the &lt;em&gt;implementation&lt;/em&gt; of Reflection. It is introduced as a set of static methods provided by the global &lt;strong&gt;Reflect object&lt;/strong&gt;, which consists of a collection of related functions rather than properties. It provides &lt;em&gt;static methods&lt;/em&gt; that allow for the invocation of interceptable &lt;em&gt;internal methods of JavaScript objects&lt;/em&gt;. These functions, introduced in ES6, establish an API for introspecting and manipulating objects and their properties.&lt;/p&gt;

&lt;p&gt;The Reflect object serves as a convenient namespace that encapsulates a set of functions &lt;em&gt;replicating the behaviour&lt;/em&gt; of core language syntax and duplicating the functionality of existing Object functions. While the Reflect functions themselves do not introduce new features, they consolidate these features into a unified and convenient API.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Example 1 - Accessing properties:&lt;/u&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Example object
const myObject = {
  name: 'John',
  age: 25
};

// Using Reflect to get a property value
const name = Reflect.get(myObject, 'name');

// Without using Reflect to get a property value
const name = myObject['name']; // or myObject.name 

console.log(name); // Output: "John"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;u&gt;Example 2 - Set properties:&lt;/u&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myObject = {
  name: 'John',
  age: 25
};

// Using Reflect.set() to update a property value
Reflect.set(myObject, 'age', 30);

// Without using Reflect to set a property value
myObject['age'] = 30; // or myObject.age = 30

// Result
console.log(myObject.age); // Output: 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;u&gt;Example 3 - Invoke a target function with a specified this value and a set of arguments:&lt;/u&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const obj = {
  name: 'John',
  greet() {
    console.log(`Hello, ${this.name}!`);
  }
};

const greetFunc = obj.greet;
const args = [];

// Using Reflect.apply() to invoke the greet method on the obj object
Reflect.apply(greetFunc, obj, args);

// Without using Reflect
greetFunc.apply(obj, args); 

// Output: "Hello, John!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way, it's worth noting that mentioning Reflect.apply() during interviews when discussing binding context can be quite impressive. It showcases a deeper understanding of JavaScript's function invocation mechanisms, going beyond just mentioning call, apply, and bind.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Example 4 - Retrieve an array of all property keys, including both enumerable and non-enumerable:&lt;/u&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const obj = {
  name: 'John',
  age: 25
}

Object.defineProperty(obj, 'address', {
  value: '123 Main St',
  enumerable: false
});

const symbolKey = Symbol('id');
Object.defineProperty(obj, symbolKey, {
  value: 123,
  enumerable: false
});

// Using Reflect.ownKeys()
const keys = Reflect.ownKeys(obj);

// Without Reflect
const keys = Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj));

// Result
console.log(keys); // Output: ['name', 'age', 'address', Symbol(id)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's important to note that Reflect is not intended to be used as a constructor. It cannot be invoked with the new operator or treated as a regular function. All properties and methods of the Reflect object are static, mirroring the behaviour of the Math object.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Example 5 - Let's also create our own implementation of the Reflect object to gain a better understanding of its functionality:&lt;/u&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Reflect {

  static get(target, propertyKey, receiver) {
    if (typeof target !== 'object' || target === null) {
      throw new TypeError('Reflect.get called on non-object');
    }
    return target[propertyKey];
  }

  static set(target, propertyKey, value, receiver) {
    if (typeof target !== 'object' || target === null) {
      throw new TypeError('Reflect.set called on non-object');
    }
    target[propertyKey] = value;
    return true;
  }

  static apply(target, thisArg, args) {
    if (typeof target !== 'function') {
      throw new TypeError('Reflect.apply called on non-function');
    }
    return target.apply(thisArg, args);
  }

  static ownKeys(target) {
    if (typeof target !== 'object' || target === null) {
      throw new TypeError('Reflect.ownKeys called on non-object');
    }
    return Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target));
  }

  // Additional Reflect methods can be implemented here
}

// Example usage:
const myObject = {
  name: "John",
  age: 25
};

console.log(Reflect.get(myObject, "name")); // Output: "John"
console.log(Reflect.set(myObject, "age", 30)); // Output: 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;So, Reflect API in JavaScript provides a powerful set of methods that enable metaprogramming capabilities. By leveraging reflection, developers can gain insight into program structures, dynamically modify behaviour, and achieve advanced program analysis. The Reflect API offers a convenient and unified approach to interact with objects, mimicking core language syntax and providing an efficient way to access and manipulate properties, invoke functions, and work with object metadata. By harnessing the capabilities of the Reflect API, developers can take their programming to the next level, empowering them to build more flexible, dynamic, and intelligent applications.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can find the comprehensive list of available methods of the Reflect object &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
      <category>metaprogramming</category>
    </item>
    <item>
      <title>Understanding SQL Joins: A Beginner's Guide</title>
      <dc:creator>Katherine Mykhailyk</dc:creator>
      <pubDate>Sun, 30 Apr 2023 23:42:32 +0000</pubDate>
      <link>https://dev.to/katerinamykhailyk/understanding-sql-joins-a-beginners-guide-bkn</link>
      <guid>https://dev.to/katerinamykhailyk/understanding-sql-joins-a-beginners-guide-bkn</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56t02pcm8iia9615sjdy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56t02pcm8iia9615sjdy.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are three main types of joins in SQL: &lt;strong&gt;INNER&lt;/strong&gt;, &lt;strong&gt;OUTER&lt;/strong&gt;, and &lt;strong&gt;CROSS&lt;/strong&gt; joins. Each join involves two tables, referred to as the LEFT and RIGHT tables, respectively. &lt;/p&gt;

&lt;p&gt;By combining these concepts, you can create different types of joins such as inner, left outer, right outer, and full outer joins. &lt;/p&gt;

&lt;p&gt;It's crucial to keep in mind that when you use the JOIN keyword without specifying the type of join, it will be treated as an INNER JOIN by default. To perform an outer join, you need to specify whether it's a RIGHT, LEFT, or FULL join. Moreover, it's worth noting that the INNER and OUTER keywords are optional with INNER being the default. &lt;/p&gt;

&lt;p&gt;For presentational purposes I created two DB tables (I use SQL Server and Azure Data Studio visual tool):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;PaymentSystems Table:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Customers Table:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Let's examine how the various types of joins can impact the outcome of a query using the example of these two tables. &lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Inner type of joins&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. INNER JOIN (or simply JOIN)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The diagram for INNER JOIN, depicts the overlapping area between two circles, which represents the rows in each table that have a common value. When this type of join is used, only the rows that have matching values in both tables will be selected and returned. In other words, INNER JOIN returns only the data that is common to both tables.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60fmqpuec250zvihil8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60fmqpuec250zvihil8k.png" alt="Image description" width="372" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s assume the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM dbo.PaymentSystems S
INNER JOIN dbo.Customers C
ON S.Id = C.PaymentSystemId
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the above code will produce the following result: &lt;/p&gt;

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

&lt;p&gt;As shown in the result, the INNER JOIN did not include certain rows from the Customers table in the final output, as those rows did not have an Id that matched the condition specified in the ON clause: S.Id = C.PaymentSystemId.&lt;/p&gt;

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

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Outer type of joins&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. LEFT OUTER JOIN (or simply LEFT JOIN)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It retrieves all the rows from the left table and any matching rows from the right table. If there are no matching rows in the right table, NULL values are used instead. &lt;/p&gt;

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

&lt;p&gt;Let's execute this query and observe the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM dbo.Customers C
LEFT JOIN dbo.PaymentSystems S
ON C.PaymentSystemId = S.Id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;As shown in the result, the LEFT OUTER JOIN retrieved all the rows from the Customers table, but only those rows from the PaymentSystems table that matched the condition specified in the ON clause: C.PaymentSystemId = S.Id. In cases where there was no match found, the missing values were replaced with NULL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. RIGHT OUTER JOIN (or simply RIGHT JOIN)&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;It returns all the rows from the right table and matching rows from the left table. If there are no matches in the left table, NULL values are returned. It's similar to LEFT OUTER JOIN, but the tables are reversed, with the right table being the primary table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM dbo.PaymentSystems S
RIGHT JOIN dbo.Customers C
ON S.Id = C.PaymentSystemId
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The outcome of the query will be as follows:&lt;/p&gt;

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

&lt;p&gt;The Customers table has been included completely, but PaymentSystems table is only included where it met the condition S.Id = C.PaymentSystemId.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. FULL OUTER JOIN (or simply FULL JOIN)&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;It retrieves all rows from both tables, and if there are any unmatched rows, it fills in the columns with NULL values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM dbo.PaymentSystems S
FULL OUTER JOIN dbo.Customers C
ON S.Id = C.PaymentSystemId
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;As you can see, this code returns a result set that includes all the rows from both the PaymentSystems and Customers tables, regardless of whether there is a matching row in the other table. The result set will have NULL values in any columns where there is no match between the two tables. &lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;Cartesian type of joins&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. CROSS JOIN&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;A CROSS JOIN produces a result set that combines each row from the first table with each row from the second table, resulting in a &lt;a href="https://en.wikipedia.org/wiki/Cartesian_product"&gt;Cartesian product&lt;/a&gt; of the two tables. It should be used with caution as it can generate a large number of rows and cause performance issues. Cross joins are appropriate when no other join can be used, and when the WHERE clause can limit the result set to a manageable size. Although a cross join doesn't make sense for my particular tables, we can still use it to illustrate how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT TOP 14 * FROM  dbo.Customers C
CROSS JOIN dbo.PaymentSystems S
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The resulting output displays all the possible combinations of rows from the Customers and PaymentSystems tables, as generated by the cross join operation. As you can see, I have limited the output by using the TOP 14 clause in order to restrict the number of rows returned by the query.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;&lt;strong&gt;No obvious category&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. SELF JOIN&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is no specific keyword in SQL for a self join. Self join doesn't belong to any of the traditional join categories such as inner, outer, left, right, or full outer join. It's a type of a instruction where a table is joined with itself. In other words, a self join is a regular join, but the table is used as both the left and right table in the join. This can be useful when you have a table that contains a hierarchy or a relationship between rows, and you need to join rows within the same table based on that hierarchy or relationship. &lt;/p&gt;

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

&lt;p&gt;A self join is utilised when a table needs to reference data within itself, for example: employees, multi-level marketing, machine parts, comment tree where each comment references the next one, and so on. &lt;/p&gt;

&lt;p&gt;The following example demonstrates a simple implementation of a self join with the help of LEFT JOIN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT *
FROM dbo.Employees E
LEFT JOIN dbo.Employees MA
ON MA.EmployeeId = E.ManagerId
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can also use the following query with a WHERE clause:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Select * FROM dbo.Employees E, dbo.Employees MA
WHERE MA.EmployeeId = E.ManagerId
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way to obtain the same result is by using an INNER JOIN :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM dbo.Employees E
INNER JOIN dbo.Employees MA
ON MA.EmployeeId = E.ManagerId
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three queries shown above are examples of self-joins where the Employees table is joined with itself.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In conclusion, SQL joins provide a powerful way to combine data from multiple tables. Understanding the differences between joins is essential for building complex queries and retrieving the data you need. By mastering SQL joins, you can unlock the full potential of your database and gain deeper insights into your data.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>beginners</category>
      <category>database</category>
      <category>programming</category>
    </item>
    <item>
      <title>C# Extension Methods: the basics you need to know</title>
      <dc:creator>Katherine Mykhailyk</dc:creator>
      <pubDate>Wed, 26 Apr 2023 03:04:28 +0000</pubDate>
      <link>https://dev.to/katerinamykhailyk/c-extension-methods-the-basics-you-need-to-know-164i</link>
      <guid>https://dev.to/katerinamykhailyk/c-extension-methods-the-basics-you-need-to-know-164i</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk44o87nybaiqc4ijmjbk.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk44o87nybaiqc4ijmjbk.jpeg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Extension methods are a powerful feature (introduced in C# 3.0) in object-oriented programming languages that allow a method to be added to an object, including a class or a type, after it has been compiled.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When creating extension methods, you would typically use static methods within static classes and the “this” modifier. Although extension methods are static, they can be invoked as if they were instance methods. However, extension methods cannot be defined for static classes, and they cannot override methods of a class or interface. If an extension method has the same name and signature as a class or interface method, it will not be called. Additionally, at compile time, instance methods defined in the type itself will always have a higher priority than extension methods.&lt;/p&gt;

&lt;p&gt;Extension methods are actually widely used in C# development and is often leveraged indirectly through popular libraries like LINQ, which uses extension methods to add query functionality to existing types such as &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.ienumerable?view=net-8.0" rel="noopener noreferrer"&gt;System.Collections.IEnumerable&lt;/a&gt; and  &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1?view=net-7.0" rel="noopener noreferrer"&gt;System.Collections.Generic.IEnumerable&lt;/a&gt;. This allows developers to query collections with great ease and flexibility. For example:&lt;/p&gt;

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

List&amp;lt;int&amp;gt; numbers = new List&amp;lt;int&amp;gt; { 1, 2, 3, 4, 5 };
var result = numbers.Where(n =&amp;gt; n % 2 == 0).Select(n =&amp;gt; n * n);


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

&lt;/div&gt;

&lt;p&gt;The following logic is performed behind the scenes (simplified code of Where and Select LINQ methods):&lt;/p&gt;

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

public static class MyLinqExtensions
{
    public static IEnumerable&amp;lt;T&amp;gt; Where&amp;lt;T&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; source, Func&amp;lt;T, bool&amp;gt; predicate)
    {
        foreach (T item in source)
        {
            if (predicate(item))
            {
                yield return item;
            }
        }
    }

    public static IEnumerable&amp;lt;TResult&amp;gt; Select&amp;lt;TSource, TResult&amp;gt;(this IEnumerable&amp;lt;TSource&amp;gt; source, Func&amp;lt;TSource, TResult&amp;gt; selector)
    {
        foreach (TSource item in source)
        {
            yield return selector(item);
        }
    }
}


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

&lt;/div&gt;

&lt;p&gt;Extension methods provide a more convenient way of writing code, leading to improved readability and discoverability. For example, consider the following two code snippets:&lt;/p&gt;

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

// Case 1: We don't have extension methods and need to use static methods

var total = Enumerable.Aggregate(
                Enumerable.Distinct(
                    Enumerable.Select(
                        Enumerable.Where(myList, x =&amp;gt; x.price &amp;gt; 5)
                       , x.price)
                    )
               , (total, next) =&amp;gt; total + next);

// Case 2: We have extension methods

var total = myList.Where(x =&amp;gt; x.price &amp;gt; 5)
                  .Select(x =&amp;gt; x.price)
                  .Distinct()
                  .Aggregate((total, next) =&amp;gt; total + next);


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;The following extension methods use cases are among the most popular:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1) The most significant benefit of using extension methods is that they provide a convenient means of adding extra features to the .Net Framework or third-party classes that cannot be modified or don’t have access to the source code. For example:&lt;/p&gt;

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

// The UserManager class that is part of the 
// Microsoft.AspNetCore.Identity library has been extended
// by adding a new method called FindByPhoneNumberAsync

public static class UserManagerExtension
{
    public static async Task&amp;lt;AppUser?&amp;gt; FindByPhoneNumberAsync(this UserManager&amp;lt;AppUser&amp;gt; userManager, string? phoneNumber)
    {
        return await userManager.Users.FirstOrDefaultAsync(u =&amp;gt; u.PhoneNumber == phoneNumber);
    }
}

// Example of use

var user = await _userManager.FindByPhoneNumberAsync(phoneNumber);


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

&lt;/div&gt;

&lt;p&gt;2) Extending the functionalities on a DTO. For example:&lt;/p&gt;

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

// Our DTO

public class TransferDTO
{
  public int Id {get;set;}
  public string Name {get;set;}
}

// Extension method

public static class TransferDTOExtension 
{
    public static int GetName(this TransferDTO transfer) 
    {
        return transfer.Name;
    }
}

// Example of use

var transfer = new TransferDTO();
Console.WriteLine(transfer.GetName()); // Extra functionality!


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

&lt;/div&gt;

&lt;p&gt;3) Collection Functionality. This is basically what we have seen higher. They allow the functionality to be called from any collection such as an System.Array or System.Collections.Generic.List that implements System.Collections.Generic.IEnumerable on that type.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In conclusion, extension methods in C# provide a powerful and flexible way to extend existing types without modifying their source code. They enable developers to add new functionality to types, including third-party types or types that are part of the .NET framework. Extension methods also make code more readable by allowing developers to write fluent and concise code. However, it is important to use extension methods judiciously and avoid creating ambiguous or confusing code. When used appropriately, extension methods can be a valuable tool for improving code quality and maintainability in C#.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>dotnetcore</category>
      <category>dotnetframework</category>
    </item>
  </channel>
</rss>
