<?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: Naresh Babu</title>
    <description>The latest articles on DEV Community by Naresh Babu (@purimetlanareshbabu).</description>
    <link>https://dev.to/purimetlanareshbabu</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%2F1139040%2Fc7253776-77ff-4370-b6e7-8f9f9694a3d6.jpeg</url>
      <title>DEV Community: Naresh Babu</title>
      <link>https://dev.to/purimetlanareshbabu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/purimetlanareshbabu"/>
    <language>en</language>
    <item>
      <title>Strategy Design Pattern</title>
      <dc:creator>Naresh Babu</dc:creator>
      <pubDate>Mon, 25 Nov 2024 03:48:00 +0000</pubDate>
      <link>https://dev.to/purimetlanareshbabu/strategy-design-pattern-1h5j</link>
      <guid>https://dev.to/purimetlanareshbabu/strategy-design-pattern-1h5j</guid>
      <description>&lt;p&gt;The Strategy Design Pattern is a &lt;strong&gt;behavioral design pattern&lt;/strong&gt; that enables &lt;strong&gt;selecting an algorithm's behavior at runtime&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Instead of &lt;strong&gt;implementing multiple variations of an algorithm in a single class&lt;/strong&gt;, it allows you to &lt;strong&gt;define a family of algorithms, encapsulate each in its own class&lt;/strong&gt;, and make them interchangeable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Components of the Strategy Pattern (UML):
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Context Class: Maintains a reference to a Strategy object and interacts with it through a common interface.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; The User class interacts with different strategies for Quality and AdPolicy.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Strategy Interface: Defines a common interface for all concrete strategies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; Quality and ADPolicies are abstract interfaces defining behavior.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Concrete Strategies: Implement the Strategy interface with specific algorithms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; FreeUserQuality, PremiumUserQuality, BasicUserQuality, FreeUserAdPolicy, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When to Use the Strategy Pattern
&lt;/h2&gt;

&lt;p&gt;Use the Strategy Pattern when the benefits of flexibility and maintainability outweigh the overhead of managing multiple strategy classes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Many Algorithms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you need to define multiple variations of an algorithm or behavior within a single class.&lt;/li&gt;
&lt;li&gt;Example: Defining video quality for different subscription plans (Free, Basic, Premium).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Runtime Decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the behavior of a class needs to change dynamically based on user input or other runtime conditions.&lt;/li&gt;
&lt;li&gt;Example: Selecting compression algorithms (ZIP, RAR, 7z) at runtime.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Avoid Excessive Use of if or switch Statements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace conditional logic with interchangeable strategy classes.&lt;/li&gt;
&lt;li&gt;Example: Payment processing (Credit Card, PayPal, UPI) without a massive if-else block.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Encapsulation of Variations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encapsulate algorithm variations in separate classes to keep the context class clean.&lt;/li&gt;
&lt;li&gt;Example: Logging strategies (ConsoleLogger, FileLogger, RemoteLogger).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open/Closed Principle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the system is open for extension but closed for modification by adding new strategies without altering existing code.&lt;/li&gt;
&lt;li&gt;Example: Adding a new user type (EnterpriseUserQuality) in the example system.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Example:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from abc import ABC, abstractmethod
from enum import Enum

# Enum for User Types
class UserType(Enum):
    FREE = 0
    BASIC = 1
    PREMIUM = 2

# Strategy Interface for Quality
class Quality(ABC):
    @abstractmethod
    def get_quality(self):
        pass

# Strategy Interface for Ad Policy
class AdPolicy(ABC):
    @abstractmethod
    def has_ads(self):
        pass

# Concrete Strategy for Quality
class FreeUserQuality(Quality):
    def get_quality(self):
        return ['SD']

class BasicUserQuality(Quality):
    def get_quality(self):
        return ['SD', 'HD']

class PremiumUserQuality(Quality):
    def get_quality(self):
        return ['SD', 'HD', 'UHD']

# Concrete Strategy for Ad Policy
class FreeUserAdPolicy(AdPolicy):
    def has_ads(self):
        return True

class BasicUserAdPolicy(AdPolicy):
    def has_ads(self):
        return True

class PremiumUserAdPolicy(AdPolicy):
    def has_ads(self):
        return False

# Context Class
class User:
    def __init__(self, user_type: UserType, quality: Quality, ad_policy: AdPolicy):
        self.user_type = user_type
        self.quality = quality
        self.ad_policy = ad_policy

    def get_quality(self):
        return self.quality.get_quality()

    def has_ads(self):
        return self.ad_policy.has_ads()

# Usage
free_user = User(UserType.FREE, FreeUserQuality(), FreeUserAdPolicy())
basic_user = User(UserType.BASIC, BasicUserQuality(), BasicUserAdPolicy())
premium_user = User(UserType.PREMIUM, PremiumUserQuality(), PremiumUserAdPolicy())

print("Free User Quality:", free_user.get_quality())  # ['SD']
print("Free User Ads:", free_user.has_ads())          # True

print("Premium User Quality:", premium_user.get_quality())  # ['SD', 'HD', 'UHD']
print("Premium User Ads:", premium_user.has_ads())          # False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advantages of the Strategy Pattern:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Flexibility: Algorithms can be swapped at runtime without altering the context class.&lt;/li&gt;
&lt;li&gt;Extensibility: New strategies can be added without modifying existing code.&lt;/li&gt;
&lt;li&gt;Readability and Maintenance: Reduces clutter in the main class by delegating logic to specific strategy classes.&lt;/li&gt;
&lt;li&gt;Adherence to SOLID Principles: Particularly supports the Open/Closed Principle.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Disadvantages of the Strategy Pattern:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Increased Complexity: Introduces additional classes and objects to manage.&lt;/li&gt;
&lt;li&gt;Overhead: If the number of strategies is small or infrequently changed, the pattern might add unnecessary complexity.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Additional Examples
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sorting Algorithms: Using different sorting strategies (e.g., QuickSort, MergeSort, BubbleSort) dynamically.&lt;/li&gt;
&lt;li&gt;Discount Calculation: Applying different discount strategies (FlatDiscount, PercentageDiscount) based on user type.&lt;/li&gt;
&lt;li&gt;Authentication Mechanisms: Switching between different authentication methods (OAuth, JWT, BasicAuth).&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>lld</category>
      <category>systemdesign</category>
      <category>designpatterns</category>
      <category>python</category>
    </item>
    <item>
      <title>Database Locking</title>
      <dc:creator>Naresh Babu</dc:creator>
      <pubDate>Mon, 14 Aug 2023 18:29:32 +0000</pubDate>
      <link>https://dev.to/purimetlanareshbabu/database-locking-32kn</link>
      <guid>https://dev.to/purimetlanareshbabu/database-locking-32kn</guid>
      <description>&lt;p&gt;There are two main types of locks in a Relational Database Management System (RDBMS):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shared (Read) Locks:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Shared locks are used when a transaction wants to read data from a resource (rows in a table).&lt;/li&gt;
&lt;li&gt;Multiple transactions can hold shared locks on the same resource simultaneously, allowing for concurrent reading.&lt;/li&gt;
&lt;li&gt;Shared locks do not prevent other transactions from acquiring their own shared locks.&lt;/li&gt;
&lt;li&gt;Any write operations are required to wait until the read lock is released.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example: SELECT * ... FOR SHARE&lt;/p&gt;

&lt;p&gt;django version: &lt;br&gt;
    objects.filter() or similar methods, the resulting queryset will acquire shared locks by default&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;with transaction.atomic():
  model_obs_to_update=
  model.objects.filter(some_condition)
  #extra logic here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Exclusive Locks:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Exclusive locks are used when a transaction wants to modify data in a resource. They prevent any other transaction from acquiring any lock (shared or exclusive) on the same resource.&lt;/li&gt;
&lt;li&gt;Exclusive locks ensure that only one transaction can modify a resource at a time, maintaining data consistency. Once lock is acquired other transactions updating/reading same records will be blocked and can resume once lock is released&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example: SELECT * ... FOR UPDATE&lt;/p&gt;

&lt;p&gt;django version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model_ids = [1, 2, 3, 4]
with transaction.atomic():
  model_obs_to_update=
  model.objects.select_for_update().filter(id__in=model_ids)
  #extra logic here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lock will be released when transaction is either committed or rolled back.&lt;/p&gt;

&lt;p&gt;In addition to these lock types, some databases support special locking behaviors:&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;When a transaction uses the NOWAIT option, it tries to acquire a lock. If the lock cannot be acquired immediately because the resource is already locked by another transaction, the transaction returns an error immediately rather than waiting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example: SELECT * ... FOR UPDATE NOWAIT&lt;/p&gt;

&lt;p&gt;django version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model_ids = [1, 2, 3, 4]
with transaction.atomic():
  model_obs_to_update=
  model.objects.select_for_update(nowait=True).filter(id__in=model_ids)
  #extra logic here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Skip Locked:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The SKIP LOCKED option is used to skip over rows that are already locked by another transaction when using an FOR UPDATE or FOR SHARE clause. This allows a transaction to work on the next available row without waiting for the locked row to be released.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example: SELECT * ... FOR UPDATE SKIP LOCKED&lt;/p&gt;

&lt;p&gt;These lock types and behaviors are essential for managing concurrency and ensuring data integrity in database systems. Proper use of locks helps to prevent conflicts between multiple transactions attempting to access and modify the same data simultaneously.&lt;/p&gt;

</description>
      <category>database</category>
    </item>
  </channel>
</rss>
