<?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: Sivakumar Natarajan</title>
    <description>The latest articles on DEV Community by Sivakumar Natarajan (@sivan2503).</description>
    <link>https://dev.to/sivan2503</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%2F2503761%2F2dbb757d-1833-4861-9a61-c45003f5061d.jpg</url>
      <title>DEV Community: Sivakumar Natarajan</title>
      <link>https://dev.to/sivan2503</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sivan2503"/>
    <language>en</language>
    <item>
      <title>OOP - Abstraction - Part 2</title>
      <dc:creator>Sivakumar Natarajan</dc:creator>
      <pubDate>Sun, 08 Dec 2024 10:49:44 +0000</pubDate>
      <link>https://dev.to/sivan2503/oop-abstraction-part-2-2f8g</link>
      <guid>https://dev.to/sivan2503/oop-abstraction-part-2-2f8g</guid>
      <description>&lt;h2&gt;
  
  
  What ?
&lt;/h2&gt;

&lt;p&gt;We have already looked at Part1 of the definition &lt;a href="https://dev.to/sivan2503/oop-abstraction-295k"&gt;here&lt;/a&gt;. Now let's dive deep into the part 2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Part 2:&lt;/em&gt;&lt;/strong&gt; Abstraction is the process of &lt;strong&gt;hiding implementation details from users&lt;/strong&gt;, enabling them to focus on the functionality rather than the internal workings.&lt;/p&gt;

&lt;p&gt;note: &lt;strong&gt;&lt;em&gt;Users&lt;/em&gt;&lt;/strong&gt; in the definition points to developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why (hide implementation details) ?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; &lt;em&gt;A new service importing an already existing reusable authentication setup.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A usual setup as part of the authentication process is to hash user passwords before comparing them with stored credentials. However, for a user of this reusable Authentication class, it suffices for them to know if a given credential is valid or not; it's not necessary for them to know about this particular hashing logic, as it's an implementation detail.&lt;/p&gt;

&lt;p&gt;In the above scenario, by hiding the implementation detail we gained benefits like,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Controlled access&lt;/em&gt; (users can't access the hashing setup)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Focus on the WHAT rather than the HOW&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Reduced complexity/cognitive load&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Reduced maintenance efforts&lt;/em&gt; - Because the hashing process is not open for users, if there is a need to change the hashing algorithm it's simple to refactor as no one else is using it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How
&lt;/h2&gt;

&lt;p&gt;There are several ways to hide implementation detail to achieve abstraction. However, let's focus on using the abstract keyword to maintain consistency with the examples from Part 1 and ensure the explanation remains intuitive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Scenario:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Designing a coffee machine capable of making a variety of coffee flavours&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ofcourse, there are several ways to achieve this, and that's the beauty of software programming. However, one effective way to implement such a coffee machine is by using abstraction — hiding the implementation details and allowing the user or programmer to focus on selecting the desired coffee flavour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Solution&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The below code snippet uses partial abstract class that's explained in detail on &lt;a href="https://dev.to/sivan2503/oop-abstraction-295k"&gt;part 1 of this blog post&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type CupSize = "small" | "medium" | "large";

type CoffeeTemperature = "hot" | "warm" | "ice";

type Milk = "almond" | "semi-skimmed" | "full-fat" | "skimmed";

// Partial abstract class with all implementation details hidden
abstract class CoffeeMachine {
  private cupSize: CupSize;
  private coffeeTemperature: CoffeeTemperature;
  private milk: Milk | undefined;
  constructor(
    cupSize: CupSize,
    coffeeTemperature: CoffeeTemperature,
    milk?: Milk
  ) {
    this.cupSize = cupSize;
    this.coffeeTemperature = coffeeTemperature;
    this.milk = milk;
  }
  private setCoffeeCupSize() {
    console.log(`set Coffee cup size to - ${this.cupSize}`);
  }

  private heatWater() {
    console.log(`heating water to default temperature`);
  }

  private addMilk() {
    this.milk
      ? console.log(`milk addition - ${this.milk}`)
      : console.log(`no milk added`);
  }

  private setCoffeeTemperature() {
    console.log(
      `heating coffee to provided temperature - ${this.coffeeTemperature}`
    );
  }

  // the only abstract method
  protected abstract addExtras(): void;

  public makeCoffee() {
    this.setCoffeeCupSize();
    this.heatWater();
    this.addMilk();
    this.setCoffeeTemperature();
    this.addExtras();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Introducing Cappuccino flavour:&lt;/p&gt;

&lt;p&gt;Now it's straight forward to introduce any new flavour as we have an abstract class with all implementation details that is hidden away from the developer extending the machine to one more flavour.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Subclass inheriting concrete methods from CoffeeMachine but als extends an abstract method
class Cappuccino extends CoffeeMachine {
  constructor(
    cupSize: CupSize,
    temperaturemilk: CoffeeTemperature,
    milk?: Milk
  ) {
    super(cupSize, temperaturemilk, milk);
  }

  protected addExtras(): void {
    console.log(`adding Cappuccino coffee pod`);
  }
}

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

&lt;/div&gt;



&lt;p&gt;Making the coffee&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const coffee = new Cappuccino("large", "hot", "almond");
// makeCoffee on Cappuccino object works here because its inherited from CoffeeMachine
coffee.makeCoffee();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In summary, abstraction is a cornerstone of object-oriented programming that simplifies complex systems by hiding unnecessary details and exposing only the essential features. By defining clear blueprints or contracts, abstraction promotes code clarity, consistency, and extensibility. It allows developers to focus on higher-level design while ensuring the underlying implementation remains flexible and reusable.&lt;/p&gt;

&lt;p&gt;Through the examples provided, we’ve seen how abstraction helps streamline workflows, encourages adherence to design principles, and makes systems easier to maintain and scale. Whether using abstract classes, interfaces, or encapsulated methods, abstraction is a powerful tool for building robust and efficient software systems.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OOP - Abstraction - Part 1</title>
      <dc:creator>Sivakumar Natarajan</dc:creator>
      <pubDate>Wed, 04 Dec 2024 22:25:31 +0000</pubDate>
      <link>https://dev.to/sivan2503/oop-abstraction-295k</link>
      <guid>https://dev.to/sivan2503/oop-abstraction-295k</guid>
      <description>&lt;h2&gt;
  
  
  What ?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Definitions&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Part 1:&lt;/em&gt;&lt;/strong&gt; Abstraction provides a &lt;strong&gt;&lt;em&gt;blueprint or plan for designing classes&lt;/em&gt;&lt;/strong&gt; with a defined set of rules. It ensures consistency and enforces that certain behaviors are implemented across derived classes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Part 2:&lt;/em&gt;&lt;/strong&gt;  Abstraction is the process of &lt;em&gt;&lt;strong&gt;hiding implementation details from users&lt;/strong&gt;&lt;/em&gt;, enabling them to focus on the functionality rather than the internal workings. &lt;/p&gt;

&lt;p&gt;Eg: A commonly used analogy is the TV remote control: users interact with buttons to operate the TV without needing to know how the internal mechanics work.&lt;/p&gt;

&lt;p&gt;I find &lt;strong&gt;&lt;em&gt;Part 1&lt;/em&gt;&lt;/strong&gt; to be more intuitive and easy to explain so this post explains in detail &lt;em&gt;Part 1&lt;/em&gt; of the definition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Part 2&lt;/em&gt;&lt;/strong&gt; &lt;a href="https://dev.to/sivan2503/oop-abstraction-part-2-2f8g"&gt;is explained in detail here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a blueprint?
&lt;/h2&gt;

&lt;p&gt;To understand the need for abstraction (a blue print), let’s first explore a problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem:
&lt;/h3&gt;

&lt;p&gt;Imagine creating classes to draw pictures of animals. Each animal has its own unique features, but certain traits—such as having four legs and a tail—are shared among them. Without a structured approach, developers might forget to include these common traits, leading to incomplete or inaccurate depictions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DogPicture {
  drawATail() {}

  drawFourLegs() {}

  drawFloppyEars() {}
}

class CatPicture {
  drawATail() {}

  drawFourLegs() {}

  drawConeShapedEars() {}
}

class HorsePicture {
  drawATail() {}

  drawFourLegs() {}

  drawManeHair() {}
}

class GoatPicture {
  drawATail() {}

  drawFourLegs() {}

  drawHorns() {}
}

class ZebraPicture {
  drawATail() {}

  drawFourLegs() {}

  drawStripesOnBody() {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solution:
&lt;/h3&gt;

&lt;p&gt;Abstraction can solve this problem by defining a shared plan or rules that every animal picture class must follow. This can be achieved using an abstract class or interface in TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abstract class AnimalPicture {
  abstract drawFourLegs(): void;

  abstract drawATail(): void;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, any class that implements AnimalPicture must define these methods. Failing to do so will result in an error.&lt;/p&gt;

&lt;h4&gt;
  
  
  Incorrect implementation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DogPicture implements AnimalPicture { // this will throw error as `drawFourLegs` &amp;amp; `drawATail` are not implemented. 
  drawFloppyEars() {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Error:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class 'DogPicture' incorrectly implements class 'AnimalPicture'. Did you mean to extend 'AnimalPicture' and inherit its members as a subclass?
  Type 'DogPicture' is missing the following properties from type 'AnimalPicture': drawFourLegs, drawATailts(2720)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Correct implementation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DogPicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a dog.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a dog.");
  }
  drawFloppyEars() {}
}

class CatPicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a cat.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a cat.");
  }
  drawConeShapedEars() {}
}

class HorsePicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a horse.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a horse.");
  }
  drawManeHair() {}
}

class GoatPicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a goat.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a goat.");
  }
  drawHorns() {}
}

class ZebraPicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a zebra.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a zebra.");
  }
  drawStripesOnBody() {}
}

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

&lt;/div&gt;



&lt;p&gt;This ensures that all animal picture classes implement the shared rules (drawFourLegs and drawATail), while allowing flexibility for unique features like floppy ears or stripes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of abstract classes:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  - Pure abstract class
&lt;/h3&gt;

&lt;p&gt;These classes are plain blueprints that won't have any concrete/implemented methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// pure abstract class
abstract class AnimalPicture {
  abstract drawFourLegs(): void;

  abstract drawATail(): void;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Typescript these pure abstract classes (with no access privilege needs like protected) can be replaced with interfaces which is as well could as a blue print.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// interface
interface AnimalPicture {
  drawFourLegs(): void;

  drawATail(): void;
}

//usage
class HorsePicture implements AnimalPicture {
  drawFourLegs(): void {
    console.log("Drawing four legs for a horse.");
  }
  drawATail(): void {
    console.log("Drawing four legs for a horse.");
  }
  drawManeHair() {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  - Impure/partial abstract class:
&lt;/h3&gt;

&lt;p&gt;Abstract classes that have one or more concrete methods along with a few abstract attributes(methods/properties).&lt;/p&gt;

&lt;p&gt;These classes can be extended(inherited) to create sub classes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Defining the abstract class&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// impure abstract class
abstract class AnimalPicture {
  // Concrete method 1
  protected drawFourLegs() {
    console.log(`drawing common four legs feature`);
  }

  // Concrete method 2
  protected drawATail() {
    console.log(`drawing common tail feature`);
  }

  // Abstract method 1
  protected abstract drawUniqueFeature(): void;

  // Concrete method 3
  public drawFinalPicture() {
    this.drawATail();
    this.drawFourLegs();
    this.drawUniqueFeature();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Extending the abstract class&lt;/strong&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 DogPicture extends AnimalPicture {
  // because its inheritance, calling the super/parent class is required.
  constructor() {
    super();
  }
  // Abstract method 1 implemented
  protected drawUniqueFeature(): void {
    console.log("Drawing four legs for a dog.");
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&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 dog = new DogPicture();
// Concrete method 3 of abstract class is inherited
dog.drawFinalPicture();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part1(&lt;em&gt;abstract as blueprint&lt;/em&gt;) Conclusion
&lt;/h2&gt;

&lt;p&gt;Abstraction in OOP helps enforce a consistent structure across related classes while allowing flexibility for unique implementations. It ensures that essential behaviors are not overlooked, making code more predictable and maintainable.&lt;/p&gt;

&lt;p&gt;Also, &lt;a href="https://dev.to/sivan2503/oop-abstraction-part-2-2f8g"&gt;please carryon reading the part2 post&lt;/a&gt; to understand the part2 of the definition.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OOPS - Inheritance</title>
      <dc:creator>Sivakumar Natarajan</dc:creator>
      <pubDate>Sat, 30 Nov 2024 13:21:36 +0000</pubDate>
      <link>https://dev.to/sivan2503/oops-inheritance-39kb</link>
      <guid>https://dev.to/sivan2503/oops-inheritance-39kb</guid>
      <description>&lt;h2&gt;
  
  
  What ?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Inheritance&lt;/em&gt;&lt;/strong&gt; concept allows a class to inherit properties and behaviors from another class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why ?
&lt;/h2&gt;

&lt;p&gt;Let's understand the necessity of inheritance and the problem that it solves using an example. &lt;/p&gt;

&lt;p&gt;Task:&lt;/p&gt;

&lt;p&gt;Build a website that allows users to view and handle their electricity account. It should have the below pages,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dashboard&lt;/li&gt;
&lt;li&gt;Account summary&lt;/li&gt;
&lt;li&gt;Payments page
and more importantly the pages should be visible only to logged in user. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find below some pseudo code that could achieve the task in hand,&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dashboard page:&lt;/em&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 Dashboard {
  login() {
    // some logic to login the user
    console.log(`User logged in successfully`);
  }
}

const dashObj = new Dashboard();
dashObj.login();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Payments page:&lt;/em&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 PaymentPage {
  login() {
    // some logic to login the user
    console.log(`User logged in successfully`);
  }
}

const payObj = new PaymentPage();
payObj.login();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;AccountSummary page:&lt;/em&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 AccountSummaryPage {
  login() {
    // some logic to login the user
    console.log(`User logged in successfully`);
  }
}

const accObj = new AccountSummaryPage();
accObj.login();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Redundancy&lt;/code&gt;: Each class repeats the same login() method. As the number of pages grows, so does the duplication of this logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintainability: If the login logic changes, every class needs to be updated, increasing the risk of errors.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to solve? (Inheritance to rescue)
&lt;/h2&gt;

&lt;p&gt;We can solve the problem by extracting the common functionality (login) into a base class. The individual page classes will then inherit this functionality. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Parent/Base class:&lt;/em&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 LoginParent {
  login() {
    // some logic to login the user
    console.log(`User logged in successfully`);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Child classes inheriting the parent's method/members:&lt;/em&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 DashboardChild extends LoginParent {}

class PaymentPageChild extends LoginParent {}

class AccountSummaryChild extends LoginParent {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Usage:&lt;/em&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 dash = new DashboardChild();
dash.login();

const pay = new PaymentPageChild();
pay.login();

const acc = new AccountSummaryChild();
acc.login();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advantages:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Reusability: The login() method is defined once in the base class and reused across all pages.&lt;/li&gt;
&lt;li&gt;Maintainability: Any updates to the login() logic need to be made only in the base class, reducing the scope for errors.&lt;/li&gt;
&lt;li&gt;Clarity: The code for each page focuses only on page-specific functionality, keeping the implementation clean and focused.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When to Use Inheritance?
&lt;/h2&gt;

&lt;p&gt;Inheritance is useful when:&lt;/p&gt;

&lt;p&gt;Classes share common functionality that is central to their behavior.&lt;br&gt;
You want to adhere to the DRY (Don’t Repeat Yourself) principle.&lt;br&gt;
You aim to create a hierarchical structure to represent relationships between entities.&lt;/p&gt;

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

&lt;p&gt;Inheritance simplifies code by promoting reusability and maintainability. By moving shared logic into a base class, we can eliminate redundancy, making the application easier to scale and manage.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OOP - Encapsulation</title>
      <dc:creator>Sivakumar Natarajan</dc:creator>
      <pubDate>Sat, 30 Nov 2024 13:20:10 +0000</pubDate>
      <link>https://dev.to/sivan2503/oops-encapsulation-3d9g</link>
      <guid>https://dev.to/sivan2503/oops-encapsulation-3d9g</guid>
      <description>&lt;h2&gt;
  
  
  &lt;em&gt;What ???&lt;/em&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Encapsulation&lt;/em&gt;&lt;/strong&gt; is the process of bundling data &amp;amp; functions into a single unit (i.e., capsule), it can also limit access to some of the data/methods.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is one of the four pillars of OOP, along with Inheritance, Polymorphism, and Data Abstraction.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Why ?&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;It's easier to take a blind assumption and proceed using encapsulation at all places, but its important to understand the why so you could use it the right way. &lt;/p&gt;

&lt;p&gt;Let's try to understand the why(s) by looking at an example task.&lt;/p&gt;

&lt;h4&gt;
  
  
  Task:
&lt;/h4&gt;

&lt;p&gt;Build a student result calculator that should,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calculate the average mark&lt;/li&gt;
&lt;li&gt;Determine if a student is failed or passed&lt;/li&gt;
&lt;li&gt;Throw error if any of the subjects mark is invalid ( &amp;lt; 0 || &amp;gt; 100)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Solution 1: the non-encapsulated way&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The idea is to just to solve the problem, so I have chosen the &lt;em&gt;Procedural programming&lt;/em&gt; way of achieving it which I believe could show good contrast between the two solutions and make the problems of the non-encapsulated approach more obvious.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Subject = "english" | "maths";

interface IStudent {
  name: string;
  marks: Record&amp;lt;Subject, number&amp;gt;;
}

// Receive Input
const studentInput: IStudent = {
  name: "John",
  marks: {
    english: 100,
    maths: 100,
  },
};

// Step1: Validate the provided marks
Object.keys(studentInput.marks).forEach((subjectName) =&amp;gt; {
  const mark = studentInput.marks[subjectName as Subject];
  if (mark &amp;gt; 100 || mark &amp;lt; 0) {
    throw new Error(`invlid mark found`);
  }
});

// Step2: find the total marks
const totalMarks = Object.keys(studentInput.marks).reduce(
  (accumulator: number, current: string) =&amp;gt;
    studentInput.marks[current as Subject] + accumulator,
  0
);

// Step3: find the average
const average = totalMarks / Object.keys(studentInput.marks).length;

// Step4: find the result
const boolResult = average &amp;gt; 40;

// Step 5: print result
console.log(boolResult);
console.log(average);

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Problems with Solution 1:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This definitely achieves the expected result but there are several problems associated to it. To name a few,&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Every implementation here is globally accessible and there is no control over its usage by future contributors.&lt;/li&gt;
&lt;li&gt;Data &amp;amp; operations are separate making it hard to trace which functions affect the data. You would have to carefully go through every piece of code to understand what is called and part of an execution.&lt;/li&gt;
&lt;li&gt;Functions become harder to manage as the logic scales. Changes can break unrelated code due to tight coupling.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to solve the problem ?
&lt;/h2&gt;

&lt;p&gt;By incorporating Encapsulation or make it more obvious by doing the below two steps, &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Controlled Access to Data &amp;amp; functions&lt;/li&gt;
&lt;li&gt;Bundling Data with Behaviour&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Solution 2: The Encapsulated way&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type SubjectNames = "english" | "maths";

interface IStudent {
  name: string;
  marks: Record&amp;lt;SubjectNames, number&amp;gt;;
}

class ResultCalculator {
  protected student: IStudent;
  constructor(student: IStudent) {
    this.student = student;
  }

  isPassed(): boolean {
    let resultStatus = true;
    Object.keys(this.student.marks).forEach((subject: string) =&amp;gt; {
      if (this.student.marks[subject as SubjectNames] &amp;lt; 40) {
        resultStatus = false;
      }
    });
    return resultStatus;
  }

  getAverage(): number {
    this.validateMarks();
    return this.totalMarks() / this.subjectCount();
  }

  private validateMarks() {
    Object.keys(this.student.marks).forEach((subject: string) =&amp;gt; {
      if (
        this.student.marks[subject as SubjectNames] &amp;lt; 0 ||
        this.student.marks[subject as SubjectNames] &amp;gt; 100
      ) {
        throw new Error(`invalid mark`);
      }
    });
  }

  private totalMarks() {
    return Object.keys(this.student.marks).reduce(
      (acc, curr) =&amp;gt; this.student.marks[curr as SubjectNames] + acc,
      0
    );
  }

  private subjectCount() {
    return Object.keys(this.student.marks).length;
  }
}

// Receive Input
const a: IStudent = {
  name: "jingleheimer schmidt",
  marks: {
    english: 100,
    maths: 100,
  },
};

// Create an encapsulated object
const result = new ResultCalculator(a);

// Perform operations &amp;amp; print results
console.log(result.isPassed());
console.log(result.getAverage());

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

&lt;/div&gt;



&lt;p&gt;notice in the above solution, &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Methods &lt;code&gt;totalMarks&lt;/code&gt;, &lt;code&gt;subjectCount&lt;/code&gt;, &lt;code&gt;validateMarks&lt;/code&gt; &amp;amp; the member variable &lt;code&gt;student&lt;/code&gt; are not exposed and can only be used by the class object. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;2.the data &lt;code&gt;student&lt;/code&gt; is bundled with every behaviour of it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>oop</category>
      <category>encapsulation</category>
    </item>
  </channel>
</rss>
