<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Shrawan Baral|Computer Engineer|AI Enthusiast|Cybersecurity|Web Developer]]></title><description><![CDATA[Shrawan Baral|Computer Engineer|AI Enthusiast|Cybersecurity|Web Developer]]></description><link>https://shrawanbaral.com.np</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Apr 2026 03:05:06 GMT</lastBuildDate><atom:link href="https://shrawanbaral.com.np/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Design Patterns for Fun]]></title><description><![CDATA[Howdy Everyone! 🤠

I always try to find a pattern while learning and implementing something. Patterns serve the predictability of operation, structure and behavior. For instance, If you know how academic writing structure works, you find it easy to ...]]></description><link>https://shrawanbaral.com.np/design-patterns-for-fun</link><guid isPermaLink="true">https://shrawanbaral.com.np/design-patterns-for-fun</guid><category><![CDATA[Software Engineering]]></category><category><![CDATA[software development]]></category><category><![CDATA[Python]]></category><category><![CDATA[design patterns]]></category><dc:creator><![CDATA[shrawan baral]]></dc:creator><pubDate>Sat, 22 Jul 2023 04:36:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/chcyjyRQV74/upload/3da0b8bfa3b139f93784f8e355cf7ff7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Howdy Everyone! 🤠</p>
<blockquote>
<p>I always try to find a pattern while learning and implementing something. Patterns serve the predictability of operation, structure and behavior. For instance, If you know how academic writing structure works, you find it easy to predict what will possibly come next in the paragraph or paper.</p>
</blockquote>
<p>Design patterns specifically are reusable solutions to common software design problems. They provide a structured and organized approach to designing software, making it more maintainable, scalable, and flexible.</p>
<p>These design patterns can be classified into 3 main groups based on purpose and application such as:</p>
<ol>
<li><p><strong>Creational Design Patterns:</strong> They focus on object creation mechanisms, providing ways to create objects in a manner suitable for a specific situation helping decouple the system from the details of object creation. For instance: Factory Method, Abstract Factory Method, Singleton, Builder, Prototype patterns.</p>
</li>
<li><p><strong>Structural Design Patterns:</strong> They deal with object composition, providing ways to organize classes and objects to form larger structures and focus on simplifying the structure of the system. For instance: Adapter, Decorater, Facade, Composite, and Proxy patterns.</p>
</li>
<li><p><strong>Behavioral Design Patterns:</strong> They focus on how objects interact and communicate with each other by defining communication patterns between classes. For instance: Command, Observer, Strategy, and Iterator patterns.</p>
</li>
</ol>
<h3 id="heading-exploring-facade-proxy-and-command-patterns">Exploring Facade, Proxy and Command Patterns</h3>
<h4 id="heading-a-facade-pattern">A. Facade Pattern</h4>
<p>We have been implementing facades knowingly/unknowingly all the time. The Facade pattern provides a unified interface to a complex subsystem, making it easier for clients to interact with the system by encapsulating the complexity and intricacies of the subsystem behind a simple API, shielding the client from the internal details.</p>
<p>Let us suppose: We have a multimedia system with an audio player and a video. Each component may have its various methods and configurations but we want to confine the component complexities within themselves.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AudioPlayer</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">play_audio</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Playing audio..."</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VideoPlayer</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">play_video</span>(<span class="hljs-params">self</span>):</span>
        print(<span class="hljs-string">"Playing video..."</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MultimediaFacade</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.audio_player = AudioPlayer()
        self.video_player = VideoPlayer()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">play</span>(<span class="hljs-params">self</span>):</span>
        self.audio_player.play_audio()
        self.video_player.play_video()

my_multimedia = MultimediaFacade()

<span class="hljs-comment"># Turning my multimedia on </span>
my_multimedia.play()

<span class="hljs-comment"># Playing audio...</span>
<span class="hljs-comment"># Playing video...</span>
</code></pre>
<p>From the above code, we can see how the complex details of turning on of multimedia system are encapsulated by the <code>play()</code> method of <code>MultimediaFacade</code> class. The <code>MultimediaFacade</code> class acts as a facade for the multimedia system encapsulating individual components - <code>AudioPlayer</code>, <code>VideoPlayer</code>.</p>
<h4 id="heading-b-proxy-pattern">B. Proxy Pattern</h4>
<p>The proxy pattern acts as a powerful tool to control access to objects and add additional functionalities without altering their core behavior. It is a structural design pattern that acts as a surrogate or placeholder for another object, allowing managing access to the real object and performing various tasks before or after its execution.</p>
<p>It is especially useful in scenarios where direct access to the real object is not desirable or when we need to add extra features, such as logging, access control, caching, or lazy initialization or when we want to prevent heavy resource utilization.</p>
<p>Let's consider a scenario: We have a Resource object that represents a heavy computational task in which we want to optimize the resource usage by caching its results.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> abc <span class="hljs-keyword">import</span> ABC, abstractmethod

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractResource</span>(<span class="hljs-params">ABC</span>):</span>
<span class="hljs-meta">    @abstractmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute_task</span>(<span class="hljs-params">self, task_name</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteResource</span>(<span class="hljs-params">AbstractResource</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute_task</span>(<span class="hljs-params">self, task_name</span>):</span>
        print(<span class="hljs-string">f"Executing task '<span class="hljs-subst">{task_name}</span>'..."</span>)
        <span class="hljs-comment"># Simulate heavy computational task here</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">f"Result of '<span class="hljs-subst">{task_name}</span>' task"</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProxyResource</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self._real_resource = ConcreteResource()
        self._cache = {}

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute_task</span>(<span class="hljs-params">self, task_name</span>):</span>
        <span class="hljs-keyword">if</span> task_name <span class="hljs-keyword">in</span> self._cache:
            print(<span class="hljs-string">f"Fetching cached result for task '<span class="hljs-subst">{task_name}</span>'..."</span>)
            <span class="hljs-keyword">return</span> self._cache[task_name]
        <span class="hljs-keyword">else</span>:
            result = self._real_resource.execute_task(task_name)
            self._cache[task_name] = result
            <span class="hljs-keyword">return</span> result


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    resource_proxy = ProxyResource()

    <span class="hljs-comment"># First execution of the task (not in cache)</span>
    task1_result = resource_proxy.execute_task(<span class="hljs-string">"Task 1"</span>)
    print(task1_result)

    <span class="hljs-comment"># Second execution of the same task (cached)</span>
    task1_result_cached = resource_proxy.execute_task(<span class="hljs-string">"Task 1"</span>)
    print(task1_result_cached)

    <span class="hljs-comment"># Another task execution (not in cache)</span>
    task2_result = resource_proxy.execute_task(<span class="hljs-string">"Task 2"</span>)
    print(task2_result)
</code></pre>
<p>The <code>ProxyResource</code> class implements the <code>Resource</code> interface as a proxy for the real resource holding a reference to the real resource and maintaining a cache to store the results of executed tasks.</p>
<blockquote>
<p>Note: Implementing cache logic directly into <code>execute_task()</code> may not be a good approach but for simplicity. For cleaner implementation, cache hit or miss can be encapsulated in its own <code>Cache</code> class.</p>
</blockquote>
<h4 id="heading-c-command-pattern">C. Command Pattern</h4>
<p>The Command pattern is a behavioral design pattern that encapsulates a request as an object, allowing clients to parameterize and decouple the sender and receiver of a request. And what I mean by decoupling is the separation of concerns. Furthermore, we can implement undo/redo functionality, deferred execution, and logging of commands.</p>
<p>For exceptional reference regarding a more depth explanation of design patterns, look for the references below.</p>
<p>But for now:</p>
<p>Let's create a simple calculator application with the <code>Calculator</code> class, which supports basic operations like addition and subtraction as command objects.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> abc <span class="hljs-keyword">import</span> ABC, abstractmethod

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Command</span>(<span class="hljs-params">ABC</span>):</span>
<span class="hljs-meta">    @abstractmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AddCommand</span>(<span class="hljs-params">Command</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, x, y</span>):</span>
        self.x = x
        self.y = y

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.x + self.y

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SubtractCommand</span>(<span class="hljs-params">Command</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, x, y</span>):</span>
        self.x = x
        self.y = y

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.x - self.y

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.command = <span class="hljs-literal">None</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">set_command</span>(<span class="hljs-params">self,command</span>):</span>
        self.command = command

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute_command</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.command.execute()

calculator = Calculator()

add_command = AddCommand(<span class="hljs-number">20</span>, <span class="hljs-number">5</span>)
subtract_command = SubtractCommand(<span class="hljs-number">4</span>, <span class="hljs-number">2</span>)

calculator.set_command(add_command)
result_add = calculator.execute_command()

print(result_add)

calculator.set_command(subtract_command)
result_subtract = calculator.execute_command()

print(result_subtract)
</code></pre>
<p>A single <code>execute_command()</code> method is called over <code>Calculator</code> class, which takes a <code>Command</code> object as an argument. Due to this, the execution output of the calculator is different based on the command that is passed to the instance of <code>Calculator</code>. Thus, we are now able to parameterize clients with different requests.</p>
<h2 id="heading-design-patterns-the-fun-part">Design Patterns: The Fun Part</h2>
<p>Till now we have learned about 3 different design patterns, you'll be amazed to know the core reason for this blog is yet to come.</p>
<p>Problem: I have to hit 3rd party API (let it be Google search API), and respond to the client after processing, but I have to do it in a way that's more manageable, reliable and if we stack a new search API in our core, it should not hurt the overall code structuring.</p>
<p>Let's define an implementation class of our 3rd party API.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> abc <span class="hljs-keyword">import</span> ABC, abstractmethod
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> os

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">API</span>(<span class="hljs-params">ABC</span>):</span>
<span class="hljs-meta">    @abstractmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GenericSearchAPI</span>(<span class="hljs-params">API</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,url</span>):</span>
        self.url = url
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self,query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GoogleAPI</span>(<span class="hljs-params">GenericSearchAPI</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,*args,**kwargs</span>):</span>
        self._access_key = os.getenv(<span class="hljs-string">'access_key'</span>)
        super().__init__(self,*args,**kwargs)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        res = requests.get(<span class="hljs-string">f"<span class="hljs-subst">{self.url}</span>/?search=<span class="hljs-subst">{query}</span>&amp;access_key=<span class="hljs-subst">{self._access_key}</span>"</span>).json()
        <span class="hljs-keyword">return</span> res
</code></pre>
<p>We want a domain linguistic for our search domain, our ubiquitous language. Let's suppose we are working in a finance company, we would like to call our search engine as <code>Finance Lookup</code> (I just made it up, pardon me ), rather than Google API, in the future we might implement local db search so we can't direct call GoogleAPI instance and call it as our holistic <code>Finance Lookup</code> engine.</p>
<p><strong>Using our knowledge of Facade:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> abc <span class="hljs-keyword">import</span> ABC, abstractmethod
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> os

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">API</span>(<span class="hljs-params">ABC</span>):</span>
<span class="hljs-meta">    @abstractmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GenericSearchAPI</span>(<span class="hljs-params">API</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,url</span>):</span>
        self.url = url
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self,query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GoogleAPI</span>(<span class="hljs-params">GenericSearchAPI</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,*args,**kwargs</span>):</span>
        self._access_key = os.getenv(<span class="hljs-string">'access_key'</span>)
        super().__init__(self,*args,**kwargs)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        res = requests.get(<span class="hljs-string">f"<span class="hljs-subst">{self.url}</span>/?search=<span class="hljs-subst">{query}</span>&amp;access_key=<span class="hljs-subst">{self._access_key}</span>"</span>).json()
        <span class="hljs-keyword">return</span> res

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FinanceLookup</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.google_search = GoogleAPI()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lookup</span>(<span class="hljs-params">self,keyword</span>):</span>
        results = self.google_search.search(keyword)
        <span class="hljs-keyword">return</span> results

finance_lookup_engine = FinanceLookup()

keyword = <span class="hljs-string">"finance"</span>
<span class="hljs-comment"># Lookup keyword</span>
results = finance_lookup_engine.lookup(keyword)
</code></pre>
<p>But Hold On.</p>
<p>Only if in our imaginary world, our 3rd party API would let us hit API continuously, but in reality, we are Throttled to a specific number of requests per unit of time. It seems better if we cache our responses to prevent hitting 3rd party API and causing delay/no responses at all.</p>
<p>Let's use our knowledge of using proxy patterns to either limit the user from our system or cache to reply them back, the response of exact query.</p>
<p><strong>Using our knowledge of Proxy:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> abc <span class="hljs-keyword">import</span> ABC, abstractmethod
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> os

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">API</span>(<span class="hljs-params">ABC</span>):</span>
<span class="hljs-meta">    @abstractmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GenericSearchAPI</span>(<span class="hljs-params">API</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,url</span>):</span>
        self.url = url
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self,query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GoogleAPI</span>(<span class="hljs-params">GenericSearchAPI</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,*args,**kwargs</span>):</span>
        self._access_key = os.getenv(<span class="hljs-string">'access_key'</span>)
        super().__init__(self,*args,**kwargs)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        res = requests.get(<span class="hljs-string">f"<span class="hljs-subst">{self.url}</span>/?search=<span class="hljs-subst">{query}</span>&amp;access_key=<span class="hljs-subst">{self._access_key}</span>"</span>).json()
        <span class="hljs-keyword">return</span> res

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GoogleAPIProxy</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self._real_api = GoogleAPI()
        self._cache = {}

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">if</span> query <span class="hljs-keyword">in</span> self._cache:
            <span class="hljs-keyword">return</span> self._cache[query]
        <span class="hljs-keyword">else</span>:
            result = self._real_api.search(query)
            self._cache[query] = result
            <span class="hljs-keyword">return</span> result

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FinanceLookup</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.google_search = GoogleAPIProxy()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lookup</span>(<span class="hljs-params">self,keyword</span>):</span>
        results = self.google_search.search(keyword)
        <span class="hljs-keyword">return</span> results

finance_lookup_engine = FinanceLookup()

keyword = <span class="hljs-string">"finance"</span>
<span class="hljs-comment"># Lookup keyword</span>
results = finance_lookup_engine.lookup(keyword)
</code></pre>
<p>In the above code, <code>GoogleAPIProxy</code> is a proxy to <code>GoogleAPI</code> which searches the cache before hitting the actual API, to prevent excessive API hits.</p>
<p>Looks good till now right?</p>
<p>We have one more problem to be solved now. As I said earlier, we may have different search engines stacked to our <code>Finance Lookup</code>, what can we do to create a feature that allows searching using the next search engine without modifying the underlying code structure?</p>
<p>Our <code>Finance Lookup</code> is highly coupled with our <code>GoogleAPIProxy</code>. Let us give our users a choice to define which search engine to use.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> abc <span class="hljs-keyword">import</span> ABC, abstractmethod
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> os

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">API</span>(<span class="hljs-params">ABC</span>):</span>
<span class="hljs-meta">    @abstractmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GenericSearchAPI</span>(<span class="hljs-params">API</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,url</span>):</span>
        self.url = url
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self,query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GoogleAPI</span>(<span class="hljs-params">GenericSearchAPI</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,*args,**kwargs</span>):</span>
        self._access_key = os.getenv(<span class="hljs-string">'access_key'</span>)
        super().__init__(self,*args,**kwargs)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        res = requests.get(<span class="hljs-string">f"<span class="hljs-subst">{self.url}</span>/?search=<span class="hljs-subst">{query}</span>&amp;access_key=<span class="hljs-subst">{self._access_key}</span>"</span>).json()
        <span class="hljs-keyword">return</span> res

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DuckDuckGOAPI</span>(<span class="hljs-params">GenericSearchAPI</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,*args,**kwargs</span>):</span>
        self._app_name = os.getenv(<span class="hljs-string">'app_name'</span>)
        self._public_key = os.getenv(<span class="hljs-string">'public_key'</span>)
        super().__init__(self,*args,**kwargs)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        res = requests.get(<span class="hljs-string">f"<span class="hljs-subst">{self.url}</span>/?search=<span class="hljs-subst">{query}</span>&amp;app_name=<span class="hljs-subst">{self._app_name}</span>&amp;public_key=<span class="hljs-subst">{self._public_key}</span>"</span>).json()
        <span class="hljs-keyword">return</span> res

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SearchAPIProxy</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self,api</span>):</span>
        self._real_api = api
        self._cache = {}

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">search</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">if</span> query <span class="hljs-keyword">in</span> self._cache:
            <span class="hljs-keyword">return</span> self._cache[query]
        <span class="hljs-keyword">else</span>:
            result = self._real_api.search(query)
            self._cache[query] = result
            <span class="hljs-keyword">return</span> result


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SearchCommand</span>(<span class="hljs-params">ABC</span>):</span>
<span class="hljs-meta">    @abstractmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">pass</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GoogleSearchCommand</span>(<span class="hljs-params">SearchCommand</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, api</span>):</span>
        self.api = api

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">return</span> self.api.search(query)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DuckDuckGoSearchCommand</span>(<span class="hljs-params">SearchCommand</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, api</span>):</span>
        self.api = api

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">execute</span>(<span class="hljs-params">self, query</span>):</span>
        <span class="hljs-keyword">return</span> self.api.search(query)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FinanceLookup</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self</span>):</span>
        self.google_search = SearchAPIProxy(GoogleAPI())
        self.duckduckgo_search = SearchAPIProxy(DuckDuckGOAPI())
        self.current_command = <span class="hljs-literal">None</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">set_command</span>(<span class="hljs-params">self, api_choice</span>):</span>
        <span class="hljs-keyword">if</span> api_choice == <span class="hljs-string">"google"</span>:
            self.current_command = GoogleSearchCommand(self.google_search)
        <span class="hljs-keyword">elif</span> api_choice == <span class="hljs-string">"duckduckgo"</span>:
            self.current_command = DuckDuckGoSearchCommand(self.duckduckgo_search)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Invalid API choice"</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lookup</span>(<span class="hljs-params">self,keyword</span>):</span>
        results = self.current_command.execute(keyword)
        <span class="hljs-keyword">return</span> results

finance_lookup_engine = FinanceLookup()

api_choice = <span class="hljs-string">"google"</span>

<span class="hljs-comment"># Set the command based on the chosen API</span>
finance_lookup_engine.set_command(api_choice)

<span class="hljs-comment"># Lookup keyword using the selected API</span>
keyword = <span class="hljs-string">"finance"</span>
results = finance_lookup_engine.lookup(keyword)
print(results)
</code></pre>
<p>Phew !! A lot of code.</p>
<p>Let me summarize the changes I have made:</p>
<ul>
<li><p>Since Proxy behavior is needed for both 3rd party api's, rather than implementing a single Google Proxy now each instance of API's are supplied to the proxy while initializing. We have now <code>SearchAPIProxy</code> class.</p>
</li>
<li><p>The command to execute APIs is segregated as <code>GoogleSearchCommand</code> and <code>DuckDuckGoSearchCommand</code> .</p>
</li>
<li><p>Each command now executes the concrete implementation of the search APIs.</p>
</li>
</ul>
<p>Well, that's done for now. I did it just for the sake of demonstrating how some patterns can be used to achieve code readability and future mutations/modifications.</p>
<p><strong>Harnessing the Power of Design Patterns:</strong></p>
<p>By incorporating design patterns into our coding practices, we can:</p>
<ol>
<li><p><strong>Improve Code Quality</strong></p>
</li>
<li><p><strong>Reduce Code Duplication</strong></p>
</li>
<li><p><strong>Enhance Collaboration</strong></p>
</li>
<li><p><strong>Boost Flexibility and Adaptability</strong></p>
</li>
<li><p><strong>Ensure Best Practices</strong></p>
</li>
</ol>
<p><strong>BUT...</strong></p>
<p>It's important to remember that design patterns are not one-size-fits-all solutions. Careful consideration must be given to the specific problem and context when choosing and implementing design patterns. Applying design patterns where they are not necessary or appropriate can lead to unnecessary complexity and reduced maintainability.</p>
<p><strong>Wrapping up</strong></p>
<p>Design patterns are powerful tools that can help create elegant, efficient, and scalable solutions to real-world problems. By understanding and applying design patterns, we can elevate our software designs and build robust and innovative software systems.</p>
<p>You reached the end of this blog, many thanks to you for taking the patience to follow along with me. Hope it helped in any way around.</p>
<h3 id="heading-references">References:</h3>
<ul>
<li><a target="_blank" href="https://refactoring.guru/design-patterns">https://refactoring.guru/design-patterns</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Concurrency Challenges: Locks, Race Conditions, and the Python Global Interpreter Lock (GIL)]]></title><description><![CDATA[Concurrency is the ability of a system to execute multiple tasks or processes simultaneously which allows the overlapping or simultaneous execution of different parts of a program, providing the illusion of parallelism and improving overall system pe...]]></description><link>https://shrawanbaral.com.np/concurrency-challenges-locks-race-conditions-and-the-python-global-interpreter-lock-gil</link><guid isPermaLink="true">https://shrawanbaral.com.np/concurrency-challenges-locks-race-conditions-and-the-python-global-interpreter-lock-gil</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[shrawan baral]]></dc:creator><pubDate>Tue, 11 Jul 2023 00:32:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/j3Kbs-GcEXs/upload/e39348c50b6bfd864a8b020e3665271f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Concurrency is the ability of a system to execute multiple tasks or processes simultaneously which allows the overlapping or simultaneous execution of different parts of a program, providing the illusion of parallelism and improving overall system performance by increased throughput, improved response times and better resource utilization.</p>
<p>There are different models and approaches to concurrency:</p>
<ol>
<li><p><strong>Multiprocessing</strong>: Multiprocessing is a programming technique that involves executing multiple processes simultaneously to achieve concurrency. It allows programs to utilize <mark>multiple processors or cores</mark> on a computer to execute tasks in parallel. Each process operates independently and has its own memory space, program counter, and stack and leverages inter-process communication mechanisms, such as pipes, queues, shared memory, or sockets to communicate. It is suitable for <strong>CPU-bound</strong> tasks.</p>
</li>
<li><p><strong>Multithreading</strong>: <mark>A thread is a lightweight unit of execution within a process(a process within a process) which share the same memory space and resources to communicate and cooperate more efficiently than separate processes.</mark></p>
<p> Multithreading, on the other hand, is a programming technique that involves creating and managing multiple threads within a single process. Each thread operates independently and can perform its own set of instructions, potentially running in parallel on different CPU cores or time slices. However, proper synchronization mechanisms, like locks or semaphores, are needed to ensure thread safety and prevent <a target="_blank" href="https://en.wikipedia.org/wiki/Race_condition">race conditions</a>.</p>
</li>
<li><p><strong>Asynchronous Programming</strong>: Asynchronous programming revolves around non-blocking operations, where a task can initiate an operation and proceed to other tasks without waiting for the operation to complete. Instead, the task receives a notification or a callback when the operation finishes, allowing it to continue execution or perform additional work. It is typically used for <strong>I/O-bound</strong> operations(r/w to a file, networking), where waiting for I/O can be time-consuming. It leverages techniques like coroutines and event loops, to efficiently manage concurrent execution. (I will be explaining in more detail how asynchronous programming works in my further blogs)</p>
</li>
</ol>
<h2 id="heading-concurrency-challenges">Concurrency challenges:</h2>
<p><strong>Race Condition: Understanding Concurrent Access Challenges</strong></p>
<p>In concurrent programming, a race condition occurs when multiple threads or processes access <mark>shared resources </mark> concurrently for read and write operations.</p>
<p><strong>Understanding Critical Regions</strong></p>
<p>A critical region refers to a section of code or a shared resource that must be accessed atomically or exclusively. It is a portion of code where race conditions can occur if not properly synchronized. Critical regions are typically associated with shared data structures or variables that are accessed and modified by multiple threads or processes.</p>
<p><strong>Race Condition and Critical Region</strong></p>
<pre><code class="lang-python">Thread <span class="hljs-number">1</span>               Thread <span class="hljs-number">2</span>
-----------           -----------
   Read X
                        Read X
   Modify X
                        Modify X
   Write X
                        Write X
</code></pre>
<p>In the diagram above, two threads, Thread 1 and Thread 2, are concurrently accessing and modifying a shared variable X. The steps involved in a race condition are as follows:</p>
<ol>
<li><p>Both Thread 1 and Thread 2 read the value of X simultaneously.</p>
</li>
<li><p>Thread 1 modifies the value of X based on its computation.</p>
</li>
<li><p>However, before Thread 1 writes the modified value back to X, Thread 2 also modifies X based on its computation.</p>
</li>
<li><p>Thread 2 writes its modified value back to X.</p>
</li>
<li><p>Finally, Thread 1 writes its modified value back to X, overwriting the modification made by Thread 2.</p>
</li>
</ol>
<p>The outcome of the race condition depends on the specific interleaving and timing of the thread execution. As a result, the final value of X may not reflect the intended or expected result.</p>
<p>So, what's the solution?</p>
<p><strong>Preventing Race Conditions: Critical Region and Synchronization</strong></p>
<p>To prevent race conditions, critical sections need to be properly synchronized. Synchronization mechanisms, such as locks, semaphores, or mutexes, can be used to ensure exclusive access to critical regions. These mechanisms allow only one thread or process to access the critical section at a time, preventing concurrent modifications and maintaining data integrity.</p>
<p>By acquiring a lock or semaphore before entering a critical section, a thread can ensure that other threads are prevented from accessing or modifying the shared resource until it has finished its operation. Once the thread completes its operation, it releases the lock or semaphore, allowing other threads to enter the critical section.</p>
<pre><code class="lang-python">Thread <span class="hljs-number">1</span>               Thread <span class="hljs-number">2</span>
-----------           -----------
   Read X
                        Read X
   Modify X
                        Modify X
   Write X
                        Write X
</code></pre>
<p>With proper synchronization, as shown in the modified diagram above, only one thread can access the critical section at a time. This ensures that modifications to X occur sequentially, avoiding race conditions and producing the desired outcome.</p>
<p>Note:</p>
<p><code>Locks are a broad topic, and the above explanation provides a general overview of their usage. There are various types of locks, including Semaphore and Mutex, which serve similar purposes. However, their specific usage and implementation details vary. Advanced topics like single lock phase and two-phase lock go deeper into the subject. I will delve into these topics and explain how databases leverage locks to ensure atomicity and consistency in transactions in further blogs</code></p>
<h3 id="heading-so-locks-solve-the-problem-right-umm-not-really">So locks solve the problem, right? Umm. Not really</h3>
<p>You see locks, rather put our thread in some waiting state. What if the lock-acquiring thread does not release the lock at all even though it has finished its job?</p>
<p>Situation: Let each thread hold one lock while waiting to acquire another lock, which is held by another thread. As a result, all threads involved are blocked and unable to proceed, and become stuck in a circular dependency, this condition is called <strong>Deadlock</strong>.</p>
<p>That's why synchronizing your critical regions( I hope you got that 😉) is crucial to maintaining data consistency and preventing race conditions else lead to deadlocks or performance bottlenecks.</p>
<p>Don't worry we have several preventive measures to prevent deadlocks like <strong>lock ordering, lock timeout, and avoidance of nested locks.</strong></p>
<h2 id="heading-take-rest-got-lost-in-the-blog">Take Rest: Got lost in the blog</h2>
<p>Let's summarize, repeat after me: locks are one of the ways for running one thread at a time to prevent racing conditions, that's all.</p>
<p><code>Note: If you are interested in research on thread-safe data structures, atomic operations, immutable data, and message passing for other methods for thread safety. What's thread safety: basically, it's ensuring a single thread is running at a time</code></p>
<h2 id="heading-global-interpreter-lock">Global Interpreter Lock</h2>
<p>Global interpreter lock or GIL is a mechanism inherent to the CPython interpreter, the reference implementation of Python, which is a type of mutex(Lock) that <mark>ensures that only one thread executes Python bytecode at any given time</mark>.</p>
<p>The GIL provides thread safety for CPython.</p>
<p>Benefit: only one thread can execute Python bytecode at a time preventing race conditions.</p>
<p>Kind of Worry: The GIL can act as a bottleneck for CPU-bound tasks, inhibiting the full utilization of multiple CPU cores.</p>
<p><code>Note: why locks in the Python library though we have GIL, be aware that GIL is for Python bytecode.</code></p>
<p><strong>Birds Eye View of Workings of the GIL</strong></p>
<p>The GIL is implemented as a mutex, a mutual exclusion object that permits only one thread to possess it at any given time. When a thread seeks to acquire the GIL, it checks its availability. If the GIL is available, the thread acquires the lock and proceeds to execute bytecode. However, if the GIL is held by another thread, the current thread is suspended and placed in a waiting state until the GIL becomes available. Below is the general idea behind working of GIL:</p>
<pre><code class="lang-python">Main Thread:
┌───────────────────────┐
│   Acquire the GIL     │
│                       │
│   Execute Python      │
│   Bytecode (hold GIL) │
│                       │
│   Release GIL         │
│                       │
└───────────────────────┘
        ▲
        │
New Thread:
        │
   GIL unavailable
   ──────────────────┐
        ▼            │
  Wait <span class="hljs-keyword">for</span> GIL        │
  to become available │
        ▼            │
─────────────────────┘
        │
GIL becomes available
<span class="hljs-keyword">and</span> acquired by the thread
        ▼
┌───────────────────────┐
│   Execute Python      │
│   Bytecode (hold GIL) │
│                       │
│   Release GIL         │
│                       │
└───────────────────────┘
        ▲
        │
   Repeat steps <span class="hljs-keyword">for</span>
   other threads
</code></pre>
<p><strong>Mitigating the GIL's Impact</strong></p>
<p>While the GIL may restrict the parallelism of CPU-bound tasks, Python provides strategies to alleviate its impact and achieve concurrent execution in specific scenarios:</p>
<ol>
<li><p><strong>I/O-Bound Tasks</strong>: The GIL's impact on I/O-bound tasks is relatively lower since threads often spend time waiting for external operations to complete. In such cases, leveraging threads can still enhance performance by overlapping I/O operations using <code>multithreading</code> or <code>asyncio</code>.</p>
</li>
<li><p><strong>Multi-Process Execution</strong>: Python's <code>multiprocessing</code> module enables the utilization of multiple processes for genuine parallelism. Each process possesses its own Python interpreter with an independent GIL, facilitating parallel execution across multiple CPU cores.</p>
<p> <code>Note: C Extensions and Subinterpreters are great concepts implemented in recent Python versions, which provide distinct Python interpreters within a single process, each with its own GIL.</code></p>
</li>
</ol>
<p><strong>Conclusion</strong></p>
<p>Understanding locks, race conditions, and the Global Interpreter Lock (GIL) is crucial for writing efficient and thread-safe Python code. Locks manage shared resources, preventing race conditions and ensuring data consistency. While the GIL limits parallelism by allowing only one thread to execute Python bytecode at a time, alternative approaches like multi-process execution and sub-interpreters can achieve parallelism. By utilizing effective synchronization, understanding the GIL's limitations, and employing appropriate concurrency strategies, developers can create robust and efficient Python applications.</p>
<p><strong>Looking for No GIL at all:</strong></p>
<p>Please refer to other Python implementations such as Jython, IronPython, PyPy</p>
<p><strong>References:</strong></p>
<ul>
<li><p>Python Wiki - Global Interpreter Lock (GIL): <a target="_blank" href="https://wiki.python.org/moin/GlobalInterpreterLock"><strong>https://wiki.python.org/moin/GlobalInterpreterLock</strong></a></p>
</li>
<li><p>Understanding the Python GIL: <a target="_blank" href="https://realpython.com/python-gil/"><strong>https://realpython.com/python-gil/</strong></a></p>
</li>
<li><p>Locks and Semaphores in Python: <a target="_blank" href="https://docs.python.org/3/library/threading.html#locks"><strong>https://docs.python.org/3/library/threading.html#locks</strong></a></p>
</li>
<li><p>Tanenbaum, A. S. (2014). Modern Operating Systems. (4th ed.). Pearson.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Garbage Collection in Python]]></title><description><![CDATA[Garbage collection but before that let's do a quick dictionary work:
schedule = {
            "morning":"apple",
            "arvo":"orange",
            "evening":"apple"
            }

The above dictionary shows the dietary schedule. It's interesti...]]></description><link>https://shrawanbaral.com.np/garbage-collection-in-python</link><guid isPermaLink="true">https://shrawanbaral.com.np/garbage-collection-in-python</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[shrawan baral]]></dc:creator><pubDate>Wed, 21 Jun 2023 05:56:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/b25tsR8dBh0/upload/d381ccd00a793626e5b9c636db0007be.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Garbage collection but before that let's do a quick dictionary work:</p>
<pre><code class="lang-python">schedule = {
            <span class="hljs-string">"morning"</span>:<span class="hljs-string">"apple"</span>,
            <span class="hljs-string">"arvo"</span>:<span class="hljs-string">"orange"</span>,
            <span class="hljs-string">"evening"</span>:<span class="hljs-string">"apple"</span>
            }
</code></pre>
<p>The above dictionary shows the dietary schedule. It's interesting to see I have some fruits repeating for the day. If I had to find how many times a single fruit I have to eat, I would have to count how many times a fruit has been mentioned in my above schedule.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> Counter
schedule = {
            <span class="hljs-string">"morning"</span>:<span class="hljs-string">"apple"</span>,
            <span class="hljs-string">"arvo"</span>:<span class="hljs-string">"orange"</span>,
            <span class="hljs-string">"evening"</span>:<span class="hljs-string">"apple"</span>
            }

fruit_count = Counter(schedule.values())
print(fruit_count) <span class="hljs-comment">#Counter({'apple': 2, 'orange': 1})</span>
</code></pre>
<p>The above shows fruit counts in my schedule. The above result is "Reference Count" (a word used to describe the above result) of fruits in our schedule, which shows the number of times our fruit has been referenced.</p>
<h4 id="heading-lets-talk-global">Let's talk global.</h4>
<p>So, until now you know what reference count is.</p>
<p>Do you know that Python has various objects created at runtime that are readily available to you?</p>
<p>They are imported from the builtins module. (Out of scope for now)</p>
<p>Why I brought this topic here is to understand the scope, that is every object has a scope of existence, builtins provided objects have a scope of existence until the program exits, and global objects have scope within the program itself. You can access the global objects via globals().</p>
<pre><code class="lang-python">globals()
{
  <span class="hljs-string">'__name__'</span>: <span class="hljs-string">'__main__'</span>,
  <span class="hljs-string">'__builtins__'</span>: &lt;module <span class="hljs-string">'builtins'</span> (built-<span class="hljs-keyword">in</span>)&gt;,
  <span class="hljs-string">'__doc__'</span>: <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__file__'</span>: <span class="hljs-string">'&lt;stdin&gt;'</span>,
  <span class="hljs-string">'__package__'</span>: <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__loader__'</span>: &lt;<span class="hljs-class"><span class="hljs-keyword">class</span> '<span class="hljs-title">_frozen_importlib</span>.<span class="hljs-title">BuiltinImporter</span>'&gt;,
  '<span class="hljs-title">__spec__</span>':</span> <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__annotations__'</span>: {},
}
</code></pre>
<p>If you create a new object in global scope then it can be viewed using globals.</p>
<pre><code class="lang-python">egg = <span class="hljs-number">20</span>

print(globals()) 
{
  <span class="hljs-string">'__name__'</span>: <span class="hljs-string">'__main__'</span>,
  <span class="hljs-string">'egg'</span>: <span class="hljs-number">20</span>,
  <span class="hljs-string">'__builtins__'</span>: &lt;module <span class="hljs-string">'builtins'</span> (built-<span class="hljs-keyword">in</span>)&gt;,
  <span class="hljs-string">'__doc__'</span>: <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__file__'</span>: <span class="hljs-string">'&lt;stdin&gt;'</span>,
  <span class="hljs-string">'__package__'</span>: <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__loader__'</span>: &lt;<span class="hljs-class"><span class="hljs-keyword">class</span> '<span class="hljs-title">_frozen_importlib</span>.<span class="hljs-title">BuiltinImporter</span>'&gt;,
  '<span class="hljs-title">__spec__</span>':</span> <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__annotations__'</span>: {},
}
</code></pre>
<p>This code will first create an integer object called <code>egg</code> and assign it the value of 20. Then, it will print the globals dictionary. The globals dictionary contains all of the global variables that are defined in the current scope. In this case, the globals dictionary will contain the variable <code>egg</code>.</p>
<p>The key <code>egg</code> is associated with the value 20. This means that the integer object <code>egg</code> is still in use.</p>
<pre><code class="lang-python">egg = <span class="hljs-number">20</span>
ball = egg
print(globals()) 
{
  <span class="hljs-string">'__name__'</span>: <span class="hljs-string">'__main__'</span>,
  <span class="hljs-string">'egg'</span>: <span class="hljs-number">20</span>,
  <span class="hljs-string">'ball'</span>:<span class="hljs-number">20</span>,
  <span class="hljs-string">'__builtins__'</span>: &lt;module <span class="hljs-string">'builtins'</span> (built-<span class="hljs-keyword">in</span>)&gt;,
  <span class="hljs-string">'__doc__'</span>: <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__file__'</span>: <span class="hljs-string">'&lt;stdin&gt;'</span>,
  <span class="hljs-string">'__package__'</span>: <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__loader__'</span>: &lt;<span class="hljs-class"><span class="hljs-keyword">class</span> '<span class="hljs-title">_frozen_importlib</span>.<span class="hljs-title">BuiltinImporter</span>'&gt;,
  '<span class="hljs-title">__spec__</span>':</span> <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__annotations__'</span>: {},
}
</code></pre>
<p>We see that 20 has been referenced by both var egg and ball, and using the initial logic of reference count we have reference count 2 for object 20 (in a real scenario reference count for 20 is not exactly 2, python has already cached and referenced so count may be different).</p>
<p>For every new reference to an object, the garbage collector increments the reference count and decrements whenever a reference to the object is deleted.</p>
<p>That is</p>
<pre><code class="lang-python"><span class="hljs-keyword">del</span> egg
print(globals())
{
  <span class="hljs-string">'__name__'</span>: <span class="hljs-string">'__main__'</span>,
  <span class="hljs-string">'ball'</span>:<span class="hljs-number">20</span>,
  <span class="hljs-string">'__builtins__'</span>: &lt;module <span class="hljs-string">'builtins'</span> (built-<span class="hljs-keyword">in</span>)&gt;,
  <span class="hljs-string">'__doc__'</span>: <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__file__'</span>: <span class="hljs-string">'&lt;stdin&gt;'</span>,
  <span class="hljs-string">'__package__'</span>: <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__loader__'</span>: &lt;<span class="hljs-class"><span class="hljs-keyword">class</span> '<span class="hljs-title">_frozen_importlib</span>.<span class="hljs-title">BuiltinImporter</span>'&gt;,
  '<span class="hljs-title">__spec__</span>':</span> <span class="hljs-literal">None</span>,
  <span class="hljs-string">'__annotations__'</span>: {},
}
</code></pre>
<p>Here, <code>del egg</code> deletes the reference to object 20, and <code>gc</code> decrements the reference count to object 20.</p>
<p>(You know now that <code>del object</code> does not delete the object but the reference to it)</p>
<h4 id="heading-so-do-we-have-objects-with-0-reference-count-what-do-we-do-with-it">So do we have objects with 0 reference count? what do we do with it?</h4>
<p>Yes, we do, and that is what garbage collector uses to track objects and finally delete them.</p>
<p>The reference count dictionary in Python is not accessible directly but can be using <code>gc</code> module itself. However, you can access it indirectly by using the <code>sys.getrefcount()</code> function.</p>
<p>For nerds, the following code will print the reference count of the object <code>egg</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> sys

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Oval</span>:</span>
    <span class="hljs-keyword">pass</span>

egg = Oval()

print(sys.getrefcount(egg)) <span class="hljs-comment">#2</span>
</code></pre>
<p>This code will print the number of references that are currently pointing to the object <code>egg</code>.</p>
<h4 id="heading-how-does-gc-handle-when-an-objects-reference-count-reaches-0">How does <code>gc</code> handle when an object's reference count reaches 0?</h4>
<p>The garbage collector knows that the object is no longer in use and can be deleted if the reference count is 0. But, given that the object, if is still referenced in the globals or builtins dictionaries<code>gc</code> will not directly delete it.</p>
<p>Python's garbage collector is a powerful tool for managing memory. It automatically deletes objects that are no longer in use, which helps to keep memory usage low. This frees programmers from having to worry about memory management, which can be a complex and error-prone task.</p>
]]></content:encoded></item><item><title><![CDATA[Pass by Assignment in Python: What you need to know]]></title><description><![CDATA[In Python, arguments to a function are passed by assignment. This means that when you call a function, each argument is assigned to a variable in the function's scope. The variable in the function's scope then points to the same object as the variabl...]]></description><link>https://shrawanbaral.com.np/pass-by-assignment-in-python-what-you-need-to-know</link><guid isPermaLink="true">https://shrawanbaral.com.np/pass-by-assignment-in-python-what-you-need-to-know</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[shrawan baral]]></dc:creator><pubDate>Wed, 21 Jun 2023 00:06:35 GMT</pubDate><content:encoded><![CDATA[<p>In Python, arguments to a function are passed by assignment. This means that when you call a function, each argument is assigned to a variable in the function's scope. The variable in the function's scope then points to the same object as the variable that was passed in.</p>
<p>For example, consider the following code:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">spam</span>(<span class="hljs-params">eggs</span>):</span>
  print(eggs)

eggs = <span class="hljs-number">35</span>

spam(eggs) <span class="hljs-comment">#35</span>
</code></pre>
<p>When the spam() function is called, the value of eggs, which is 35, is assigned to the variable eggs in the function's scope. The <em>variable eggs in the function's scope</em> then point to the same object as the <em>variable eggs in the global scope</em>. This means that when the print() statement in the spam() function is executed, the value of the object that eggs point to will be printed.</p>
<p><strong>How is it even different from Pass by reference and Pass by value?</strong></p>
<p>All objects in Python are references, when you pass an object as an argument to a function, you are actually passing a reference to the object.</p>
<p>Then why is it not pass-by-reference then?</p>
<p>It's because the reference is not copied, it is simply assigned to a new variable in the function's scope and finally when we make changes to the object in the function's scope, those changes are reflected in the object in the calling scope. This is because the two objects are pointing to the same thing. This is kind of similar behavior to what we call pass-by-reference but not exactly how we achieve it in Python.</p>
<p>Let's see the following code:</p>
<pre><code class="lang-python">bucket_of_eggs = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>]

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">spam</span>(<span class="hljs-params">bucket_of_eggs</span>):</span>
  bucket_of_eggs.append(<span class="hljs-number">4</span>)

print(bucket_of_eggs) <span class="hljs-comment">#[1,2,3]</span>
spam(bucket_of_eggs)

print(bucket_of_eggs) <span class="hljs-comment">#[1,2,3,4]</span>
</code></pre>
<p>When the spam() function is called, the list is passed as an argument. The append() method is then called on the list in the function's scope. This appends the value 4 to the list. When the spam() function returns, the changes that were made to the list in the function's scope are reflected in the list in the calling scope. This means that the output of the print() statement will be [1, 2, 3, 4].</p>
<p>But, hold on, this mutation to the globally scoped variable is only possible for mutable data.</p>
<p>The following code may clarify further:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">spam</span>(<span class="hljs-params">eggs</span>):</span>
  eggs = eggs + <span class="hljs-number">2</span>
  print(eggs)

eggs = <span class="hljs-number">35</span>

spam(eggs) <span class="hljs-comment">#37</span>
print(eggs) <span class="hljs-comment">#35</span>
</code></pre>
<p>When the spam() function is called, the value of eggs, which is 35, is assigned to the variable eggs in the function's scope. The variable eggs in the function's scope then point to the same object as the variable eggs in the global scope. But when adding two more eggs, the new object 37 is created and referenced with the function's scope, breaking the initial reference to a global object. This means that when the print() statement in the spam() function is executed, the value of the object that eggs point to in the function scope will be printed without making any changes to the original object, which kind of like feels similar to pass-by-value which is not.</p>
<p>Pass by assignment is an important concept to understand in Python. It can be a bit confusing at first, but it is essential for understanding how Python functions work. By understanding the pass by assignment, you will be able to write more effective and efficient Python code.</p>
]]></content:encoded></item><item><title><![CDATA[OpenCV Basics]]></title><description><![CDATA[Welcome to OpenCV with Python Series for computer vision. We will explore OpenCV from basics to advanced, this article is created along my learning process about OpenCV.  The series will be different than from rest of my writing style (formal writing...]]></description><link>https://shrawanbaral.com.np/opencv-basics</link><guid isPermaLink="true">https://shrawanbaral.com.np/opencv-basics</guid><dc:creator><![CDATA[shrawan baral]]></dc:creator><pubDate>Thu, 18 Aug 2022 05:18:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/aVvZJC0ynBQ/upload/v1660801084586/r_EFqg58k.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to OpenCV with Python Series for computer vision. We will explore OpenCV from basics to advanced, this article is created along my learning process about OpenCV.  The series will be different than from rest of my writing style (formal writing) and the  article update will try to improve the article gradually. Without any further intro, let me introduce OpenCV.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> cv2
</code></pre>
<pre><code class="lang-python">img = cv2.imread(<span class="hljs-string">'cat.jpeg'</span>)
print(<span class="hljs-string">"Image is of type: "</span>,type(img))
</code></pre>
<pre><code>Image <span class="hljs-keyword">is</span> of <span class="hljs-keyword">type</span>:  <span class="hljs-operator">&lt;</span>class <span class="hljs-string">'numpy.ndarray'</span><span class="hljs-operator">&gt;</span>
</code></pre><p>This show that after reading an image OpenCV converts to numpy arrary by default. Which makes much easy to work with.</p>
<p>Displaying the image can be done in the notebook using matplotlib but if we want to display full image
we can use opencv imshow method.</p>
<pre><code class="lang-python">cv2.imshow(<span class="hljs-string">'cat'</span>,img)
cv2.waitKey(<span class="hljs-number">0</span>)
cv2.destroyAllWindows()
</code></pre>
<p>In the following code I will be using matplotlib.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt 
plt.imshow(img)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660800238106/H2hjHNsSC.png" alt="output_5_1.png" /></p>
<p>Let's view the shape of this numpy array(image)</p>
<pre><code class="lang-python">print(<span class="hljs-string">"Image shape: "</span>,img.shape)
</code></pre>
<pre><code><span class="hljs-attribute">Image</span> shape:  (<span class="hljs-number">1280</span>, <span class="hljs-number">900</span>, <span class="hljs-number">3</span>)
</code></pre><p>We have a <code>1280*900</code> pixels in 3 channels(Red, Blue and Green) each. That is if we were to calculate how many pixels make up this image then the anwser is <code>1280 X 900 X 3 = 3456000</code> pixels.</p>
<p>OpenCV provides methods to save the numpy array (image) into any format we specify as following</p>
<pre><code class="lang-python">cv2.imwrite(<span class="hljs-string">'cat.png'</span>,img)
</code></pre>
<h2 id="heading-understanding-channels">Understanding channels</h2>
<p>Till now we just explored how to read and write image, and view them. Now we will be looking into what channels are.</p>
<p>Understanding Black and white images:
These are the images with pixels that consists of either black or white colors, more specifically light intensity 0 for black and 255 for white.</p>
<p>Understanding Gray Scale images:
Whereas, they are the images with pixels storing intensities anywhere between 0 to 255. Where values near to 255 are lighter and values near to 0 are darker under different shades of grey.</p>
<p>Understanding Channels:
Channels are nothing other than color. If we say Red channel then we mean Red color, and saying a pixel in Red channel has intensity 0 will mean that there is No-Red color(shade) and saying intensity of 255 will mean we have darkest red.</p>
<p>Interestingly, we can use combination of 3 colors to generate other colors.</p>
<p><img src="https://cdn-images-1.medium.com/fit/c/192/192/1*akS8GJ6wSeVW3t_kEiRWvw.png" alt="rgb" /></p>
<p>By using combinations of Red, Blue and Green we get variety of colors.</p>
<p>We can read images in Grey Channel or in RGB. </p>
<p><em>Note: OpenCV reads image in BGR(Blue,Green,Red) order not RGB order</em></p>
<p>Reading images in Gray Scale in OpenCV</p>
<pre><code class="lang-python">grey_img = cv2.imread(<span class="hljs-string">"./cat.png"</span>,cv2.IMREAD_GRAYSCALE)
plt.imshow(grey_img)
</code></pre>
<p>Or we can even convert the read image into any other channels as</p>
<pre><code class="lang-python">converted_grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
plt.imshow(converted_grey)
</code></pre>
<p>To access the individual channel from the BGR image, we can proceed by:</p>
<pre><code class="lang-python">b,g,r = img[:,:,<span class="hljs-number">0</span>],img[:,:,<span class="hljs-number">1</span>],img[:,:,<span class="hljs-number">2</span>]
concated = cv2.hconcat([b,g,r])
plt.imshow(concated)
</code></pre>
<p>In the next article we will explore some augmentation methods available in OpenCV.</p>
]]></content:encoded></item><item><title><![CDATA[Towards creating an Intrusion Detection system]]></title><description><![CDATA[Abstract
Intrusions in network refers to all those anomalous/undesirable activities that affects the CIA’s of the security for the intention of stealing, altering data and system that serves the desire of the attacker of bringing the service down. Wi...]]></description><link>https://shrawanbaral.com.np/towards-creating-an-intrusion-detection-system</link><guid isPermaLink="true">https://shrawanbaral.com.np/towards-creating-an-intrusion-detection-system</guid><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Python]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[firewall]]></category><dc:creator><![CDATA[shrawan baral]]></dc:creator><pubDate>Wed, 10 Aug 2022 04:09:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/yekGLpc3vro/upload/v1660104493986/_WD-uqtok.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-abstract">Abstract</h2>
<p>Intrusions in network refers to all those anomalous/undesirable activities that affects the CIA’s of the security for the intention of stealing, altering data and system that serves the desire of the attacker of bringing the service down. With our heavy dependence over internet technologies, we are living in the age of inter networked digital life but along with such advancements we’re are at a constant risk in terms of security and our privacy. The attacks include DoS, DDoS, Phishing and many more, they are varied and are always changing and more sophisticated. Still at present day DoS has been a major issue for big companies serving their business online. We at our defense side must be smart enough and deal with changing patterns and detect them as early as possible.</p>
<p>This article tries to introduced machine learning approach on detecting those intrusive patterns, taking data-set reference from CICIDS2017. Where we first capture the network traffic flow in the form of .pcap files, then process it into a well structured format of data using CIC-flow-meter. We try to infer the patterns that separates benign from intrusive ones. From the analysis, it is obtained that machine learning approaches could be one of the layer for security purpose rather than supplementing signature based IDS wholly.</p>
<p>Keywords: IDS(Intrusion Detection System), IPS(Intrusion Prevention System), FP(False Positive), FN(False Negative), Benign, Intrusions,Nftables</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Using rule based system to analyze the network flow and detect the anomalies/intrusions based on their signatures stored on the database only isn’t an effective way to detect the network intrusions early for new type of intrusions that the database doesn’t consists of. We are living in the digital age where our entire business today is heavily dependent on. While having perks, we also have risks associated with it such as DoS, DDoS, Botnet, etc and many undiscovered attacks. So we want to realize such a system which learns patterns from network flows and discriminate them as desired. For that purpose we build a machine learning model based on CICIDS2017 and use a flow meter to listen and dump packets into structured form. Then for training purpose utilize <a target="_blank" href="https://imbalanced-learn.org/">smote</a> to balance the imbalanced datasets then apply pca for dimension reduction and finally use random forest classifier to create a model from these data. After inferring the model with testing data we achieved a astonishing result that implies that is can classify the unseen network flows consisting of benign and intrusive network flows pretty well. This brings us to implementing such a system which now can create firewall rules based on these predictions in order to block them from harming the system. It utilizes the batch processing of each captured flow and outputs the corresponding predictions.</p>
<h2 id="heading-objectives">Objectives</h2>
<ul>
<li>Apply Machine learning approach to build an intrusion detection system</li>
</ul>
<h2 id="heading-problem-statement">Problem statement</h2>
<p>We are heavily dependent on internet based services, with rise of digital networking we are benefited as well as are in a risk of network based attacks.The network based attacks are costly for an organization and for individuals in terms of data, privacy and service. Previously used signature based method are though simple and direct in architecture, they need to maintain huge datasets, such isn’t possible to include all attack patterns till date, also new day attack type detection isn’t possible at all until network flow verified as an attack and updated to the signature database. We require an intelligent agent that learns what is actually benign network flow, we want it to detect the flows that deviate from this profile and mark it as intrusive/suspicious as early as possible.</p>
<h2 id="heading-literature-review">Literature Review</h2>
<p>For the purpose of intrusion detection we need to create a baseline about what is traffic is normal and what is not. Further we require such a  datasets which can represent the knowledge about the feature (domain knowledge) which is valuable for the study. Searching for those datasets bring us to KDD99Cup, NSL KDD, DEFCON-8, CICIDS2017, etc. Selecting from those didn't pose such a challenge because we want such dataset that is most recent and has data entries that captures the new types of attacks. So, for the study analysis CICIDS2017 was chosen. This data set consisted of about 80% benign and 20% different types of attack types. The original creators <a class="post-section-overview" href="#References">4</a> of the dataset used random forest regressor and weighted average method for feature selection whereas some authors <a class="post-section-overview" href="#References">5</a> used principal component analysis for dimensionality reduction.</p>
<h2 id="heading-methodology">Methodology</h2>
<p>The methodology follows a ml workflow where Principal Component Analysis and Random Forest Classifier are used. The following link forwards to the implementation code. The dataset was downloaded from <a target="_blank" href="https://www.unb.ca/cic/datasets/ids-2017.html">CICIDS2017</a> website, which was processed into parquet file for fast reading of the data entries. <a target="_blank" href="https://azwyane.github.io/article/intrusion-detection(binary-classification)-with-pca-and-randomforest">Intrusion detection(Binary classification) with PCA and RandomForest</a>
For implementing IPS, we design the system in such a way where each classified flows are then prevented by creating firewall rules using net-filter nftables in Linux based operating system by automated creation of nftables block rules in input, output or forward chain. Moreover, generating what kind of rule for the each flows is more of a concern.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>From the above analysis, we could create a logically modeled solution for separating benign patterns apart from the intrusive ones based on the features extracted from the captured network packets using flow meter.</p>
<p>We could see that only applying principal component analysis setting components to be 10 such that knowledge from data doesn’t diminish for the purpose of dimentionality reduction and applying random forest classification algorithm such that the hyperparameteres used from cross validated high scoring model, we could obtain F1 score to be nearly 0.99 and roc auc to be 0.98. It shows the model learns the hidden patterns from data and is distinct on what separates benign from intrusion.</p>
<p>The study doesn’t end here rather with this kind of approach, it raises a question on what if we study on more set of features, what features have a value in determining the result.</p>
<p>Further, this study relies on flow-meter and its data structuring and its captured bidirectional flow. The input provided to the model act as an independent flow, but sophisticated attacks are sometimes made up of connected flows, it will create an ambiguity when same connection is sometime benign and anomalous.</p>
<p>While creating an IPS, the major factors we consider are False Positives and False Negatives. Both high FP and FN are unwanted but can be handled as per the purpose. This raises another intuition behind using this type of model along with other types of IDS. Controlling Benign as intrusions (FN) and intrusions as benign (FP) can be pretty straight forward if one applies manual setting for preventing mislabeling of benign
as intrusion for networks with low traffic but still using them in large scale and creating manual rules to revert predictions is still not an efficient way.</p>
<p>In further analysis we will see what other methods we can focus on getting features that are valuable using CNN and neural networks and also study what kind of IPS needs to be built for such system. In following articles we will discuss the types of approach to achieve creating varied types of rules for different kinds of attacks and block types such as specific port or ip block or entire network block . Such implementation will be targeted for network layer and for IPv4 networks only and also we will discuss the efficiency required for such system for processing huge network traffic for classifying them as Benign or Intrusions.</p>
<p>The entire source code of this could be found at : <a target="_blank" href="https://github.com/azwyane/NGuard">https://github.com/azwyane/NGuard</a></p>
<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://www.unb.ca/cic/research/applications.html">https://www.unb.ca/cic/research/applications.html</a></p>
</li>
<li><p><a target="_blank" href="http://www.unb.ca/cic/datasets/IDS2017.html">http://www.unb.ca/cic/datasets/IDS2017.html</a></p>
</li>
<li><p><a target="_blank" href="https://wiki.nftables.org/wiki-nftables/index.php/Main_Page">https://wiki.nftables.org/wiki-nftables/index.php/Main_Page</a></p>
</li>
<li><p>I. Sharafaldin, A. H. Lashkari, and A. A. Ghorbani, “Toward generating a new intrusion detection dataset and intrusion traffic characterization,” in ICISSP 2018 - Proceedings of the 4th International Conference on Information Systems Security and Privacy, 2018,vol.2018-January,pp.108–116.doi:10.5220/0006639801080116.</p>
</li>
<li><p>R. Abdulhammed, H. Musafer, A. Alessa, M. Faezipour, and A. Abuzneid, “Features dimensionality reduction approaches for machine learning based network intrusion detection,” Electronics (Switzerland), vol. 8, no. 3, Mar. 2019, doi:10.3390/electronics8030322.</p>
</li>
</ol>
]]></content:encoded></item></channel></rss>