<?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: Jay Bhavsar</title>
    <description>The latest articles on DEV Community by Jay Bhavsar (@jbhv12).</description>
    <link>https://dev.to/jbhv12</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%2F915329%2F88f27df5-54f1-4ae9-85ea-3e69d14051f8.jpeg</url>
      <title>DEV Community: Jay Bhavsar</title>
      <link>https://dev.to/jbhv12</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jbhv12"/>
    <language>en</language>
    <item>
      <title>How to Make the Most of a Cheap IPv6-Only VPS: A Guide for Self-Hosting Enthusiasts</title>
      <dc:creator>Jay Bhavsar</dc:creator>
      <pubDate>Tue, 22 Apr 2025 12:42:26 +0000</pubDate>
      <link>https://dev.to/jbhv12/how-to-make-the-most-of-a-cheap-ipv6-only-vps-a-guide-for-self-hosting-enthusiasts-1ibg</link>
      <guid>https://dev.to/jbhv12/how-to-make-the-most-of-a-cheap-ipv6-only-vps-a-guide-for-self-hosting-enthusiasts-1ibg</guid>
      <description>&lt;p&gt;Found a dirt-cheap IPv6-only VPS—maybe from v6Node, Vultr, or one of those $2/month deals? Wondering what to do with it?&lt;/p&gt;

&lt;p&gt;If you're into self-hosting, the answer is: &lt;em&gt;a lot&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Go IPv6-Only?
&lt;/h2&gt;

&lt;p&gt;IPv4 is scarce and expensive. IPv6 gives you a practically unlimited address space. That’s why many providers offer IPv6-only VPS at a huge discount.&lt;/p&gt;

&lt;p&gt;The catch? Not everything on the internet supports IPv6. But if you’re okay with a few workarounds, it’s a steal.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can You Use It For?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;VPN Server&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;My #1 reason for getting one.&lt;/p&gt;

&lt;p&gt;Set up WireGuard or OpenVPN. If that sounds like too much work, try Twingate or Tailscale:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Twingate&lt;/strong&gt;: route only selected traffic through your VPS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailscale&lt;/strong&gt;: configure it as an exit node to tunnel all traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perfect for bypassing local restrictions and improving privacy.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Dockerized Services&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run your favorite self-hosted apps. I use mine for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;qbittorrent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;jellyfin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nextcloud&lt;/code&gt; (the built-in office suite is underrated)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;linkwarden&lt;/code&gt; (bookmark manager)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bitwarden&lt;/code&gt; (password manager)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Personal Web Hosting&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Great for blogs, portfolios, or static sites. Simple and effective.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Remote Dev Environment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I run Coder on mine — lets me use a full dev environment in the cloud. I can connect using VS Code (either in the browser or locally), and even use JetBrains IDEs like IntelliJ with remote support.&lt;/p&gt;

&lt;p&gt;Feels native, runs heavy tasks on the VPS, and keeps my laptop cool.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Learning &amp;amp; Experimentation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Mess around with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New Linux distros&lt;/li&gt;
&lt;li&gt;Infrastructure as Code (Terraform, Ansible)&lt;/li&gt;
&lt;li&gt;Docker + Kubernetes basics&lt;/li&gt;
&lt;li&gt;Self-hosting monitoring stacks (Prometheus + Grafana)&lt;/li&gt;
&lt;li&gt;CI/CD experiments (GitLab Runner, Drone CI)&lt;/li&gt;
&lt;li&gt;Reverse proxies and networking (Traefik, Nginx, Caddy)&lt;/li&gt;
&lt;li&gt;Fail2ban, UFW, and SSH hardening&lt;/li&gt;
&lt;li&gt;Automating cloud backups&lt;/li&gt;
&lt;li&gt;Running your own email server (if you’re brave)&lt;/li&gt;
&lt;li&gt;Benchmarking tools and performance tuning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheap, isolated, and disposable. Ideal lab setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling IPv4-Only Clients
&lt;/h2&gt;

&lt;p&gt;If you need to expose your IPv6-only services to the IPv4 world, use a reverse proxy like &lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt;. It lets you serve your content to both IPv4 and IPv6 clients—without needing a public IPv4 address.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Happy self-hosting!&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Inversion of Control (IoC): Demystifying the Familiar Pattern</title>
      <dc:creator>Jay Bhavsar</dc:creator>
      <pubDate>Thu, 04 Apr 2024 10:51:14 +0000</pubDate>
      <link>https://dev.to/jbhv12/inversion-of-control-ioc-demystifying-the-familiar-pattern-2003</link>
      <guid>https://dev.to/jbhv12/inversion-of-control-ioc-demystifying-the-familiar-pattern-2003</guid>
      <description>&lt;p&gt;Senior devs, if you are working on fairly complex real life project, you already know and use lots of IoC principles. Here's a quick refresher with examples, without much jargon. &lt;/p&gt;

&lt;p&gt;Inversion of Control (IoC) is a design principle where control over program flow is shifted to an external framework or container, promoting flexibility and modularity. Note that it is only a principle (or philosophy). Here are some common implementations we see in real world engineering. &lt;/p&gt;

&lt;h2&gt;
  
  
  Dependecy Injection (DI)
&lt;/h2&gt;

&lt;p&gt;Ever used or defined a parameterized constructor? That's DI in nutshell. &lt;br&gt;
Instead of letting constructor figure out things on its own, you, the caller, pass parameters. Parameters in this case are dependencies, and you as a caller is injecting them. Here's an intuitive example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;precision&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// bad example, since no DI here&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;precision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;precision&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// good example, since caller can pass precision&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;precision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;precision&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Same reasoning can be applied to any method with parameters. &lt;br&gt;
Ever used &lt;code&gt;@Autowired&lt;/code&gt; in Spring? That's also DI. (more details in next section)&lt;/p&gt;

&lt;p&gt;Relating to IoC principle: With DI, control is inverted from method to caller. That's IoC.&lt;/p&gt;
&lt;h2&gt;
  
  
  Inversion of Control Containers
&lt;/h2&gt;

&lt;p&gt;IoC Containers make it easier to do DI in enterprise applications. It takes care of DI and lifecycle management (&lt;code&gt;@PostConstruct&lt;/code&gt; and &lt;code&gt;@PreDestroy&lt;/code&gt; annotations). Below are 2 code snippets, showing how code looks with and without IoC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Repository&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User saved: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 
    &lt;span class="o"&gt;}&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainApp&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User saved: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 
    &lt;span class="o"&gt;}&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainApp&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how first code is less verbose since Spring takes care of DI. Now, you might imagine how complex and messy this can get for more complex use cases. &lt;/p&gt;

&lt;p&gt;Relating to IoC principle: Control of DI in inverted from programmer to framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Template Pattern
&lt;/h2&gt;

&lt;p&gt;Ever used inheritance? That's template pattern.&lt;br&gt;
In this pattern, the control flow of an algorithm is defined in a base class, while specific steps of the algorithm can be implemented in subclasses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Beverage&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;prepareBeverage&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;boilWater&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;brew&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;pourInCup&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;brew&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addCondiments&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Common methods with default implementation, can be overridden by subclasses&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;boilWater&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Boiling water"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pourInCup&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pouring into cup"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Coffee&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Beverage&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;brew&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dripping Coffee through filter"&lt;/span&gt;&lt;span class="o"&gt;);}&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addCondiments&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Adding sugar and milk"&lt;/span&gt;&lt;span class="o"&gt;);}&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;pourInCup&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pouring into takeaway cup"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tea&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Beverage&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;brew&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Steeping the tea"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addCondiments&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Adding lemon"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sip&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sipping tea!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BeverageMaker&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Beverage&lt;/span&gt; &lt;span class="n"&gt;coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Coffee&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Making coffee..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;coffee&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prepareBeverage&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="nc"&gt;Beverage&lt;/span&gt; &lt;span class="n"&gt;tea&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Tea&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Making tea..."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;tea&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prepareBeverage&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Relating to IoC principle: Instead of relying on subclasses for implementation, control is given to abstract class to have set methods. This also allows customizations (see &lt;code&gt;Coffee.pourInCup()&lt;/code&gt; and extensions (see &lt;code&gt;Tea.sip()&lt;/code&gt;).  &lt;/p&gt;

&lt;h2&gt;
  
  
  Factory Pattern
&lt;/h2&gt;

&lt;p&gt;Factories are used to create instances of classes or components. They encapsulate the logic for creating objects, allowing for flexible instantiation based on runtime conditions. Consider following example for better understanding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IStorage&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AwsStorage&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IStorage&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="nd"&gt;@Override&lt;/span&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Storing "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" in AWS"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 
    &lt;span class="o"&gt;}&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LocalStorage&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IStorage&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="nd"&gt;@Override&lt;/span&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Storing "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" in Local FS"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 
    &lt;span class="o"&gt;}&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FTPStorage&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IStorage&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
    &lt;span class="nd"&gt;@Override&lt;/span&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;File&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Storing "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" in FTP"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; 
    &lt;span class="o"&gt;}&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StorageFactory&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;IStorage&lt;/span&gt; &lt;span class="nf"&gt;getStorage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;storageType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AWS"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storageType&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AwsStorage&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LOCAL"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storageType&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LocalStorage&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FTP"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equalsIgnoreCase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storageType&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FTPStorage&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;StorageFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStorage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AWS"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;StorageFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStorage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LOCAL"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="nc"&gt;StorageFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getStorage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FTP"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"file.txt"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Notice how client (&lt;code&gt;Main&lt;/code&gt; class) can call &lt;code&gt;getStorage()&lt;/code&gt; and &lt;code&gt;store()&lt;/code&gt; without knowing much about their implementations. &lt;code&gt;getStorage()&lt;/code&gt; is also extensible without modifying the client code. This also makes it easier to slice and dice our code to inject mock implementations for testing. &lt;/p&gt;

&lt;p&gt;Relating to IoC principle: The control of object creation in inverted from client and delegated to factory component. &lt;/p&gt;

&lt;h2&gt;
  
  
  Event Handling
&lt;/h2&gt;

&lt;p&gt;This is very common pattern seen across many programming languages. Let's start with and example:&lt;br&gt;
There's a door, and when it opens we want to alert security.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Door&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Door "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" is opening."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Security system notified: Door "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" opened."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Door&lt;/span&gt; &lt;span class="n"&gt;frontDoor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Front Door"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;frontDoor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This works okay, but there's a major problem with it as it grows more complex. Let's say client only wants to alert security based on some condition. Or let's say we want to turn on lights when door is opened. &lt;code&gt;Door&lt;/code&gt; class is tightly coupled with security and violates SRP (Single Responsibility Principle). Here's how we can fix it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DoorEvent&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt; &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DoorEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Door&lt;/span&gt; &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;door&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getDoor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DoorListener&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doorOpened&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DoorEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DoorListener&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Door&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listeners&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addDoorListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DoorListener&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;removeDoorListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DoorListener&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Door "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" is opening."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Notify all listeners that the door is opening&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DoorListener&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;listeners&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doorOpened&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DoorEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// all the external systems&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SecuritySystem&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DoorListener&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doorOpened&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DoorEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Security system notified: Door "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDoorName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" opened."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LightingSystem&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DoorListener&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doorOpened&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DoorEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Lights turned on: Door "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDoorName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" opened."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;//client&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Door&lt;/span&gt; &lt;span class="n"&gt;frontDoor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Front Door"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;SecuritySystem&lt;/span&gt; &lt;span class="n"&gt;securitySystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SecuritySystem&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;LightingSystem&lt;/span&gt; &lt;span class="n"&gt;lightingSystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LightingSystem&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;frontDoor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addDoorListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;securitySystem&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;frontDoor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addDoorListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lightingSystem&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;frontDoor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is better because control is with the caller. Caller don't need to know about interfaces or events at all. This code is also extensible, meaning we can add more implementations of `&lt;code&gt;&lt;br&gt;
&lt;/code&gt;DoorListener&lt;code&gt;without modifying&lt;/code&gt;Main&lt;code&gt;or&lt;/code&gt;Door` class.&lt;/p&gt;

&lt;p&gt;Relating to IoC principle: Here &lt;code&gt;Door&lt;/code&gt; class don't have control over handling &lt;code&gt;DoorEvent&lt;/code&gt;s. This control is now delegated &lt;code&gt;DoorListener&lt;/code&gt; (external component).&lt;/p&gt;

&lt;h2&gt;
  
  
  Aspect-Oriented Programming (AOP)
&lt;/h2&gt;

&lt;p&gt;AOP aims to separates cross-cutting concerns, such as logging, security, or transaction management, from the core business logic. It can be applied to multiple classes or components without modifying their code directly.&lt;/p&gt;

&lt;p&gt;Imagine you are tasked to add log line before and after every function call in some class &lt;code&gt;UserRepository&lt;/code&gt;. Here's how you can do it with AOP.&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;java&lt;br&gt;
@Aspect&lt;br&gt;
@Component&lt;br&gt;
public class UserRepositoryLoggingAspect {&lt;br&gt;
    @Pointcut("execution(* package.repository.UserRepository.*(..))")&lt;br&gt;
    private void userRepositoryMethods() {}&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Before("userRepositoryMethods()")
public void logBeforeMethodExecution() {
    System.out.println("Logging before method execution...");
}

@After("userRepositoryMethods()")
public void logAfterMethodExecution() {
    System.out.println("Logging after method execution...");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;Notice, how this is accomplished without even looking at code in &lt;code&gt;package.repository.UserRepository&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Relating to IoC principle: Here the control in inverted from &lt;code&gt;UserRepository&lt;/code&gt; to &lt;code&gt;UserRepositoryLoggingAspect&lt;/code&gt;. The &lt;code&gt;UserRepository&lt;/code&gt; class does not directly handle or specify the logging behavior; instead, it is automatically intercepted and augmented with logging functionality by the Spring framework.&lt;/p&gt;

&lt;p&gt;Hope this helps, let me know what you think in comments! Checkout my website for more: &lt;a href="https://jay.is-savvy.dev/"&gt;https://jay.is-savvy.dev/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OAuth Terms Explained in One Sentence</title>
      <dc:creator>Jay Bhavsar</dc:creator>
      <pubDate>Fri, 09 Feb 2024 16:31:42 +0000</pubDate>
      <link>https://dev.to/jbhv12/oauth-terms-explained-in-one-sentence-2all</link>
      <guid>https://dev.to/jbhv12/oauth-terms-explained-in-one-sentence-2all</guid>
      <description>&lt;p&gt;I made this note for a quick reference to my future self. &lt;br&gt;
OAuth 2 aimed to replace traditional session based auth, because of security and management issues.&lt;br&gt;
OAuth was originally designed to handle only authorization and not authentication. &lt;/p&gt;
&lt;h2&gt;
  
  
  Terminology
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Resource Owner
&lt;/h3&gt;

&lt;p&gt;User who own the data, the one who is trying to log in. You. &lt;/p&gt;
&lt;h3&gt;
  
  
  Client
&lt;/h3&gt;

&lt;p&gt;The app requesting your data. eg. Calendly&lt;/p&gt;
&lt;h3&gt;
  
  
  Authorization Server
&lt;/h3&gt;

&lt;p&gt;Server that verifies user's identity. eg. accounts.google.com&lt;/p&gt;
&lt;h3&gt;
  
  
  Resource Server
&lt;/h3&gt;

&lt;p&gt;Server that hosts resources needed by client. eg. api.calendar.google.com&lt;/p&gt;
&lt;h3&gt;
  
  
  Authorization Grant
&lt;/h3&gt;

&lt;p&gt;Permission from authorization server. aka &lt;code&gt;auth code&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Redirect URI
&lt;/h3&gt;

&lt;p&gt;Where to pass authorization grant. (usually back to client's servers) eg. api.client.com/callback&lt;/p&gt;
&lt;h3&gt;
  
  
  Access Token
&lt;/h3&gt;

&lt;p&gt;Token for accessing resources from  &lt;code&gt;Resource Server&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Response Type
&lt;/h3&gt;

&lt;p&gt;It can be either token or code. Code is more secure involving back channel. Passing response type=token would give you access token directly without authorization grant (auth code). &lt;/p&gt;
&lt;h3&gt;
  
  
  Scopes
&lt;/h3&gt;

&lt;p&gt;Specific granular permissions. list of scopes that authorization server understands. Client sends list of scopes to request data. eg. Permission to read your age, email, name etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  Consent
&lt;/h3&gt;

&lt;p&gt;Consent screen popping up when signing in. eg. Consent screen when logging in with Google&lt;/p&gt;
&lt;h3&gt;
  
  
  Back Channel - highly secured channel
&lt;/h3&gt;

&lt;p&gt;Backend server of client, eg. python code running in Calendly's servers&lt;/p&gt;
&lt;h3&gt;
  
  
  Front channel - less secured channel
&lt;/h3&gt;

&lt;p&gt;Browser, eg. Javascript Calendly app running on user's browser&lt;/p&gt;
&lt;h2&gt;
  
  
  Flows
&lt;/h2&gt;

&lt;p&gt;Flow, in laymen terms, means "the login/signup flow" -- process of app requesting access, user providing consent, token generated and passed back to client. There are 4 flows supported:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorization code (front channel + back channel)&lt;/li&gt;
&lt;li&gt;Implicit (front channel only)&lt;/li&gt;
&lt;li&gt;Resource owner password credentials (back channel only)&lt;/li&gt;
&lt;li&gt;Client credentials (back channel only)
## Problems with OAuth 2.0 for Authentication&lt;/li&gt;
&lt;li&gt;No standard way to get users information&lt;/li&gt;
&lt;li&gt;Every implementation is a little different&lt;/li&gt;
&lt;li&gt;No common set of scopes
## OpenID Connect
Introduced to solve the authentication problem. It is a small layer on top of OAuth. 
### OpenID scope
the only new thing added. this mean the flow is now OpenID connect flow. 
### ID token
similar to access token, but used to identify user instead of authorizing them within some scopes. it is JWT token.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Claims
&lt;/h3&gt;

&lt;p&gt;JWT token has 3 sections. header, signature and body. body is also known as claims or payload. claims is decode by the application and can be used to retrive user data.&lt;/p&gt;
&lt;h3&gt;
  
  
  /userinfo
&lt;/h3&gt;

&lt;p&gt;this endpoint is implement by the auth server as a standard. the client can hit it to get basic info like name, email and profile pic.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;This is an excellent presentation by Nate Barbettini, who clearly explains OAuth2 in simple terms. Highly recommenced watch. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/996OiexHze0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>oauth</category>
      <category>authentication</category>
      <category>authorization</category>
      <category>openid</category>
    </item>
    <item>
      <title>Scaling Cheer: A Deep Dive into the Architecture of Red Jingles AI Chatbot</title>
      <dc:creator>Jay Bhavsar</dc:creator>
      <pubDate>Fri, 15 Dec 2023 12:28:58 +0000</pubDate>
      <link>https://dev.to/jbhv12/red-jingles-a-holiday-theme-based-ai-chatbot-5fl8</link>
      <guid>https://dev.to/jbhv12/red-jingles-a-holiday-theme-based-ai-chatbot-5fl8</guid>
      <description>&lt;p&gt;A state-of-the-art holiday theme-based AI chatbot focusing on scalability, extensibility and real world applicability.&lt;/p&gt;

&lt;p&gt;Official submission to &lt;a href="https://hackathon.serverless.guru/"&gt;Serverless Holiday Hackathon 2023&lt;/a&gt; hosted by &lt;a href="https://www.serverlessguru.com/"&gt;Serverless Guru&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DuuMLuOQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/jbhv12-personal-public/rj-logo-500x500.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DuuMLuOQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/jbhv12-personal-public/rj-logo-500x500.png" alt="Red Jingles Logo" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Checkout the hosted app, Santa and the team waiting for you &lt;a href="https://red-jingles-zo5w7qkf4a-ue.a.run.app/"&gt;here&lt;/a&gt;!!&lt;/p&gt;

&lt;p&gt;Also check out &lt;a href="https://github.com/jbhv12/red-jingles"&gt;GitHub Repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Submission by:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/jbhv12/"&gt;Jay Bhavsar&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/riya-bhavsar-52237b117/"&gt;Riya Bhavsar&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Purpose and Objectives&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The world has witnessed AI's potential thanks to platforms like OpenAI. It's crucial that AI isn't just limited to tech experts but accessible to everyone.&lt;/p&gt;

&lt;p&gt;Red Jingles is our attempt to create a chatbot backed by LLM with a Christmas theme featuring Santa Claus, Snowman, and Elf.&lt;/p&gt;

&lt;p&gt;Beyond the initial fun, this interaction is more than just choosing a character. Users feel engaged, empowered, and heard when their preferences are considered instantly. This transforms the interaction from machine to virtual character, making it feel like talking to a friend.&lt;/p&gt;

&lt;p&gt;Red Jingles offers a unique, joyful AI conversation experience that doesn't feel like traditional AI. It makes interactions more personal, engaging, and fun, creating a deeper connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Functionalities and features&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication:&lt;/strong&gt; Users sign up using their email, which undergoes verification. Subsequently, they can log in using their verified email and password for application access.  We have a strong password policy in place to have a minimum 8 chars and mix of uppercase, lowercase, symbols and numerics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Selecting Christmas themed characters:&lt;/strong&gt; Users enjoy a unique and fun aspect by selecting one of three Christmas characters — &lt;em&gt;Santa Claus, Snowman&lt;/em&gt; or &lt;em&gt;Elf&lt;/em&gt;.  Each character has a unique personality and charm. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Have a conversation with AI, ask anything:&lt;/strong&gt; Centered around the holiday theme, common inquiries may revolve around gift suggestions, recipes, dinner plans, home decor, travel tips, and more, though there is no limitation for any genre. AI can access the internet to get up to date and accurate information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contextual memory:&lt;/strong&gt; Temporary memory assists the AI in quicker responses and better understanding during extended and deeper conversations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Persistent storage:&lt;/strong&gt; Users benefit from permanent storage, enabling them to refer back to previous conversations with the AI for valuable insights at any time. Users can also resume any previous conversation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API for developers:&lt;/strong&gt; We have exposed REST APIs as a separate service. It is also secured with the same auth mechanism as the chat app. It follows OpenAPI standard, and has a well documented interactive UI.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. High Level Design&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.1 Architecture Diagram&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3K6XFE_o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/jbhv12-personal-public/rj-arch.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3K6XFE_o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/jbhv12-personal-public/rj-arch.jpg" alt="Red Jingles Architecture" width="800" height="926"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt;  Chainlit Cloud has since been migrated to &lt;a href="https://cloud.getliteral.ai/"&gt;literal&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.2 Technical Components in Detail&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3.2.1 AWS Cognito&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Constructing a robust authentication system is a huge and challenging task. Recognizing that, we opted for a fully managed and serverless authentication service—Amazon’s AWS Cognito.&lt;/p&gt;

&lt;p&gt;Configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication with OAuth2 protocol&lt;/li&gt;
&lt;li&gt;Email as primary attribute&lt;/li&gt;
&lt;li&gt;Required email verification for successful signup&lt;/li&gt;
&lt;li&gt;Strong password policy to have minimum 7 characters including lowercase, uppercase, numeric and special characters&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3.2.2 Google App Engine&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;We have deployed 2 GAE services. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chainlit+Langchain application is containerized and runs on custom runtime and flexible environment. &lt;/li&gt;
&lt;li&gt;The other service runs on standard environment and python runtime which  hosts LangServe API and documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3.2.3 Memorystore (Redis)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Memorystore offers a fully managed serverless redis database. Since redis is a fast, in-memory database, we use it to store conversation context for active chats.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3.2.4 Chainlit Cloud&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Chainlit cloud is a fully managed service to store users' chat history. Behind the scenes it uses SQL databases.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3.2.5 OpenAI&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;OpenAI hosts various LLMs and offers a robust API for their models. We use these LLMs to power our app.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.3 Scalability&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Amazon Cognito
&lt;/h4&gt;

&lt;p&gt;By default, Cognito accommodates up to 40 million users. Specifically, it enables 120 Requests per Second (RPS) for user sign-ins and 50 RPS for user sign-ups (Source: Quotas in Amazon Cognito - Amazon Cognito).&lt;/p&gt;

&lt;h4&gt;
  
  
  Google App Engine (GAE)
&lt;/h4&gt;

&lt;p&gt;GAE is capable of automatically scaling up to an impressive 2,147,483,647 instances. Its most potent instance type, F4_1G, boasts 3072 MB of memory and a CPU clocked at 2.4 GHz. This scalability equates to serving millions of active users in real-world scenarios.&lt;/p&gt;

&lt;h4&gt;
  
  
  Google Memorystore
&lt;/h4&gt;

&lt;p&gt;Offering a default quota of 1 terabyte (TB) of storage per region, Memorystore for Redis becomes instrumental. Assuming an average conversation occupies 1 megabyte (MB), this allocation allows support for up to 1 million active conversations per region (Source: Quotas and limits  |  Memorystore for Redis  |  Google Cloud).&lt;/p&gt;

&lt;h4&gt;
  
  
  OpenAI API
&lt;/h4&gt;

&lt;p&gt;With its default quota, the OpenAI API facilitates up to 10,000 Requests per Minute (RPM) (Source:  Rate limits - OpenAI API).&lt;/p&gt;

&lt;h4&gt;
  
  
  Chainlit Cloud
&lt;/h4&gt;

&lt;p&gt;Despite the absence of explicitly mentioned quotas and limits on their website, Chainlit Cloud presents a managed enterprise solution. Accurate estimations can be derived by referencing a self-hosting guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.4 CI/CD Diagram&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aTfXsw_S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/jbhv12-personal-public/ci-cd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aTfXsw_S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://storage.googleapis.com/jbhv12-personal-public/ci-cd.jpg" alt="Red Jingles Architecture" width="774" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.5 CI/CD components in detail&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Git
&lt;/h4&gt;

&lt;p&gt;Git serves as a robust version control system, enabling effective codebase management. The code is open source and hosted on the widely used platform GitHub.&lt;/p&gt;

&lt;h4&gt;
  
  
  GitHub Actions
&lt;/h4&gt;

&lt;p&gt;This feature automates the processes of building and deploying code. When code is pushed, GitHub Actions triggers a sequence of actions. Firstly, it builds the Docker image and subsequently pushes it to Docker Hub. Following the successful completion of the initial action, a second action is triggered. This action executes the "terraform apply" command, implementing any alterations made to the infrastructure.&lt;/p&gt;

&lt;h4&gt;
  
  
  Docker Hub
&lt;/h4&gt;

&lt;p&gt;The chatbot application is containerized and publicly hosted on Docker Hub, a repository for Docker container images.&lt;/p&gt;

&lt;h4&gt;
  
  
  Terraform
&lt;/h4&gt;

&lt;p&gt;Terraform operates as an infrastructure-as-code tool, facilitating seamless integration across various platforms, including AWS Cognito, Google App Engine, and Google Memorystore Redis, among others. Google Cloud Storage buckets are utilized to store Terraform state files, ensuring efficient management and tracking of infrastructure changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.6 Design choices summary&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ideation thoughts for choosing a particular service:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;AWS Cognito&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Chosen over alternatives like Auth0, Okta, and Firebase due to its customizable hosted UI, which provided a straightforward and seamless configuration process.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Google App Engine (GAE)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Selected because of its minimal configuration requirements and excellent scalability. While other serverless solutions like ECS and Cloud Run could be viable, GAE's simplicity and scalability were determining factors.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;LangChain&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Its open-source nature, large active community, well-maintained documentation, and comprehensive range of tools available out of the box made it extremely user-friendly, especially for newcomers.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Chainlit&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Stood out for providing a ready-to-use solution along with infrastructure support, making it a convenient choice for the project's needs.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Google Memorystore Redis&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Chosen for its seamless compatibility with applications running on Google Cloud, full management, and serverless functionality. Although alternatives like Redis Cloud and ElastiCache were considered, its integration with GAE was a decisive factor.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;OpenAI&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Previous positive experience with their APIs led to its selection. While alternatives like AWS Bedrock and Huggingface were viable, the ease of interchangeability in the project's design made it a suitable choice.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Docker&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Its ability to establish loose coupling and isolation between application and infrastructure requirements, along with its containerization capabilities facilitating running applications on any host, made it a preferred choice.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Terraform&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Highly efficient in supporting Infrastructure as Code (IAC), enabling streamlined infrastructure management and deployment processes.&lt;/p&gt;

&lt;p&gt;Acknowledging the evolving nature of technology, we as a team remain always open to future learnings and potential adaptations to emerging tools and services.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.7 Design Challenges&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.7.1 Abrupt Disconnection of Service
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Scenario: During chat interactions, users encountered an abrupt "Service not available" error after initiating conversation, disrupting the flow of dialogue.&lt;/li&gt;
&lt;li&gt;Analysis: The application deployed on Google App Engine's flexible environment utilizes VM instances equipped with a front-end load balancer responsible for load distribution. When a user initiates a chat, the request is directed to a specific instance (I1). Subsequent queries might be routed to a different instance (I2), leading to a loss of the previously established webhooks session.&lt;/li&gt;
&lt;li&gt;Fix: Set session affinity to true to ensure the load balancer consistently directs requests from the same session to the same origin server. &lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  &lt;strong&gt;3.7.2 Configuring AWS Cognito for Chainlit Authentication&lt;/strong&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Scenario: Chainlit’s limited support for OAuth platforms lacked compatibility with AWS Cognito, creating authentication challenges.&lt;/li&gt;
&lt;li&gt;Fix: We duplicated and customized files sourced from the Chainlit library. Subsequently, modifications were made to the library during the Docker image building process. Our intention is to initiate a Pull Request (PR) on the Chainlit repository to introduce support for AWS Cognito. This implementation serves as a valuable resource for individuals aiming to integrate AWS Cognito with Chainlit, offering a clear reference point for such integration.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt;  AWS Cognito is now officially supported in Chainlit, and this workaround is not needed anymore&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;4. Low Level Design&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4.1 Directory Structure&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;There are two primary directories within the project: 'app' and 'terraform.' &lt;/p&gt;

&lt;p&gt;The 'app' directory houses all the necessary code and configurations required to execute the application. Meanwhile, the 'infra' directory contains Terraform code, enabling the creation of infrastructure components on the cloud platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4.2 Python files&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Constants.py&lt;/strong&gt;: This file serves as a central repository defining the AI characters—Santa, Snowman, and Elf. It includes their names, display names, image thumbnails, system prompts, welcome messages, and other associated attributes essential for their representation within the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent.py&lt;/strong&gt;: Responsible for defining and configuring the Langchain agent. It specifically initializes the LLM (Language Model) and allows for customization of the LLM model if needed. Additionally, it provides the capability to configure and incorporate additional tools into the agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;app.py&lt;/strong&gt;: Functions as the primary entry point for the Chainlit application. It relies on 'constants.py' and 'agent.py' as its core dependencies. Within this file, all the necessary callbacks for managing conversation handling are defined and implemented.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;api_server.py&lt;/strong&gt;: Serves as the main entry point for Langserve. This file is built using FastAPI and exposes a REST API specifically designed for the agent, facilitating communication and interaction with the AI functionalities provided by the system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4.3 Code Quality&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All the python code follows the PEP-8 styling guide. &lt;/li&gt;
&lt;li&gt;Terraform code follows the HCL style conventions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. Extensions and Real World Applicability&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enable Multi-Modal Support:&lt;/strong&gt; Enhance the capabilities of the system to incorporate a wider range of inputs and outputs, expanding beyond text-only interactions. This enhancement aims to enable the AI agent to process and generate responses using various modalities, such as images and documents, in addition to textual inputs and outputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expand Agent Functionality with Additional Tools:&lt;/strong&gt; Extend the functionality of the AI agent by integrating supplementary tools, including but not limited to email, Slack, Jira, etc. This enhancement aims to configure the agent to access and utilize various personal and productivity tools, allowing for more comprehensive and versatile interactions and task execution within the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;6. Running on Local&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;See instruction on &lt;a href="https://github.com/jbhv12/red-jingles"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;7. Links and Contact Details&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Live Red Jingles Chatbot Application: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://red-jingles-zo5w7qkf4a-ue.a.run.app/"&gt;https://red-jingles-zo5w7qkf4a-ue.a.run.app/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Red Jingles API Server: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://red-jingles.ue.r.appspot.com/docs"&gt;https://red-jingles.ue.r.appspot.com/docs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jbhv12/red-jingles"&gt;jbhv12/red-jingles (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Docker Hub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hub.docker.com/repository/docker/jbhv12/red-jingles/general"&gt;jbhv12/red-jingles general | Docker Hub&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Video Demo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.loom.com/share/9d1b08c92df144549b0ec26b4aaf8724?sid=ed711c4a-1890-4157-8d8a-f581a00da64e"&gt;Quick Application Walkthrough&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://youtu.be/jGGvGRDnU-w"&gt;Detailed Explaination&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Developers Contact Details:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Jay Bhavsar&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Email: &lt;a href="//mailto:jbhv12@gmail.com"&gt;jbhv12@gmail.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/jbhv12/"&gt;https://www.linkedin.com/in/jbhv12/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Riya Bhavsar&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Email: &lt;a href="//mailto:riyashah0895@gmail.com"&gt;riyashah0895@gmail.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/riya-bhavsar-52237b117/"&gt;https://www.linkedin.com/in/riya-bhavsar-52237b117/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>serverless</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
