<?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: Gaurav</title>
    <description>The latest articles on DEV Community by Gaurav (@gauravratnawat).</description>
    <link>https://dev.to/gauravratnawat</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%2F401818%2Fbfbc7a02-ecbd-4934-afc8-5674df87d487.jpeg</url>
      <title>DEV Community: Gaurav</title>
      <link>https://dev.to/gauravratnawat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gauravratnawat"/>
    <language>en</language>
    <item>
      <title>Transforming Engineering Culture in a 300-Person Company</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Thu, 06 Nov 2025 18:15:17 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/transforming-engineering-culture-in-a-300-person-company-35l</link>
      <guid>https://dev.to/gauravratnawat/transforming-engineering-culture-in-a-300-person-company-35l</guid>
      <description>&lt;h3&gt;
  
  
  🚀 Transforming Engineering Culture in a 300-Person Company
&lt;/h3&gt;

&lt;p&gt;A few months ago, I worked with a small company (~300 people) that had reached a breaking point in its tech journey.&lt;/p&gt;

&lt;p&gt;Here’s what I found when I joined:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No defined SDLC — ideas went straight to production.&lt;/li&gt;
&lt;li&gt;Every client had a &lt;strong&gt;custom version&lt;/strong&gt; of the product.&lt;/li&gt;
&lt;li&gt;No documentation, no tests, no CI/CD.&lt;/li&gt;
&lt;li&gt;Legacy code everywhere.&lt;/li&gt;
&lt;li&gt;Engineers had been there 8–10 years, never exposed to new tech.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result?&lt;br&gt;
Tech silos.&lt;br&gt;
Fear of change.&lt;br&gt;
Zero innovation.&lt;br&gt;
No shared vision of the future.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧩 The Real Problem
&lt;/h3&gt;

&lt;p&gt;The issue wasn’t &lt;strong&gt;people&lt;/strong&gt; it was &lt;strong&gt;the way of working&lt;/strong&gt;.&lt;br&gt;
To fix that, we needed to reshape both &lt;strong&gt;culture and process&lt;/strong&gt; without breaking the company’s rhythm.&lt;/p&gt;

&lt;p&gt;So we used a blend of &lt;strong&gt;top-down clarity&lt;/strong&gt; and &lt;strong&gt;bottom-up ownership&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔝 Top-Down Changes (Leadership-Led)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Defined a simple product goal: &lt;em&gt;move from per-client customizations to a single configurable platform.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Introduced lightweight engineering standards (code reviews, testing, CI/CD, README required).&lt;/li&gt;
&lt;li&gt;Started a small &lt;em&gt;Architecture Circle&lt;/em&gt; of 4 senior engineers for shared decision-making.&lt;/li&gt;
&lt;li&gt;Modernized one critical service instead of rewriting everything.&lt;/li&gt;
&lt;li&gt;Brought in 2 engineers from outside to spark new ideas.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ⚙️ Bottom-Up Movement (Engineer-Led)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Picked one pilot team to adopt the new process → &lt;strong&gt;30% faster release in 2 months.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Created &lt;em&gt;Backend, DevOps, and QA Guilds&lt;/em&gt; — open to anyone who wanted to learn and share.&lt;/li&gt;
&lt;li&gt;Made documentation part of “definition of done.”&lt;/li&gt;
&lt;li&gt;Celebrated every small win company wide.&lt;/li&gt;
&lt;li&gt;Paired legacy engineers with modern stack developers — building trust and skill transfer.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📈 The 12-Month Journey
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Discovery&lt;/strong&gt; – Understand what’s broken.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pilot&lt;/strong&gt; – Test the new process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foundation&lt;/strong&gt; – Scale what works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Culture&lt;/strong&gt; – Build internal momentum.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sustain&lt;/strong&gt; – Make it habit.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By the end, the company wasn’t “perfect” — but it was &lt;strong&gt;healthier&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Releases were faster and stable.&lt;/li&gt;
&lt;li&gt;Documentation became normal.&lt;/li&gt;
&lt;li&gt;Knowledge silos started breaking.&lt;/li&gt;
&lt;li&gt;People began suggesting improvements instead of resisting them.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💡 My Biggest Takeaway
&lt;/h3&gt;

&lt;p&gt;You don’t need a big budget or 100 new hires to transform.&lt;br&gt;
You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear direction (from leadership)&lt;/li&gt;
&lt;li&gt;Empowered teams (from the ground)&lt;/li&gt;
&lt;li&gt;Consistent small wins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Change doesn’t happen by mandate — it happens by &lt;strong&gt;momentum&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;👉 Have you seen a similar cultural shift in your company?&lt;br&gt;
What worked — top-down leadership, or bottom-up drive?&lt;/p&gt;

&lt;h1&gt;
  
  
  EngineeringCulture #Leadership #SoftwareDevelopment #Transformation #Agile #DevOps #ContinuousImprovement
&lt;/h1&gt;

</description>
      <category>softwareengineering</category>
      <category>leadership</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Decode Bridge Pattern</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Sun, 02 Jan 2022 06:51:49 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/decode-bridge-pattern-3a3p</link>
      <guid>https://dev.to/gauravratnawat/decode-bridge-pattern-3a3p</guid>
      <description>&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When run-time binding of the implementation is required.&lt;/li&gt;
&lt;li&gt;To support a proliferation of classes resulting from a coupled interface and numerous implementations,&lt;/li&gt;
&lt;li&gt;To share an implementation among multiple objects and to map orthogonal class hierarchies.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Intent
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Decouple an abstraction from its implementation so that the two can vary independently.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

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




&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;The Bridge pattern is an application of the old advice, "prefer composition over inheritance". It becomes handy when you must subclass different times in ways that are orthogonal with one another. Say you must implement a hierarchy of colored shapes. You wouldn't want to subclass Shape with Rectangle and Circle and then subclass Rectangle with RedRectangle, BlueRectangle and GreenRectangle and the same for Circle. You would prefer to say that each Shape has a Color and to implement a hierarchy of colors, and that is the Bridge Pattern.&lt;/p&gt;

&lt;p&gt;1 Design a color-oriented interface that is minimal, necessary, and sufficient. Its goal is to decouple the abstraction from the color. Define a derived class of that interface for each color.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.dp.bridge;

public interface Color {

  void applyColor();

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

&lt;/div&gt;



&lt;p&gt;2 Define a derived class of that interface for each color.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.dp.bridge;

public class Red implements Color {

  public void applyColor() {

    System.out.println("Red");

  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.dp.bridge;

public class Green implements Color {

  public void applyColor() {

    System.out.println("Green");

  }

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

&lt;/div&gt;



&lt;p&gt;3 Create the abstraction base class that "has a" color object and delegates the color-oriented functionality to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.dp.bridge;

public abstract class Shape {

  protected Color color;

  public Shape(Color c) {
    color = c;
  }

  public abstract void draw();

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

&lt;/div&gt;



&lt;p&gt;4 Define specializations of the abstraction class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.dp.bridge;

public class Circle extends Shape {

  public Circle(Color color) {
    super(color);
  }

  public void draw() {
    System.out.print("Draw Circle in ");
    color.applyColor();
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.dp.bridge;

public class Rectangle extends Shape {
  public Rectangle(Color color) {
      super(color);
  }

  public void draw() {
    System.out.print("Draw Rectangle in ");
    color.applyColor();
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.dp.bridge;

public class Square extends Shape {

  public Square(Color color) {
      super(color);
  }

  public void draw() {
    System.out.print("Draw Square in ");
    color.applyColor();
  }

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

&lt;/div&gt;



&lt;p&gt;5 The Client code. The Bridge Pattern allows one to mix and match without needing to create a rigid hierarchy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.dp.client;

import com.gaurav.dp.bridge.Circle;
import com.gaurav.dp.bridge.Green;
import com.gaurav.dp.bridge.Rectangle;
import com.gaurav.dp.bridge.Red;
import com.gaurav.dp.bridge.Shape;
import com.gaurav.dp.bridge.Square;

public class BridgeClient {

  public static void main(String[] args) {

    Shape[] shapes = { 
        new Circle(new Red()), 
        new Square(new Red()),
        new Rectangle(new Green()) 
        };

    for (Shape shape : shapes) {
      shape.draw();
    }

  }

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[output]
Draw Circle in Red
Draw Square in Red
Draw Rectangle in Green
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Decoupling allows us to choose the implementations at runtime.&lt;/li&gt;
&lt;li&gt;Compile-time dependencies on the implementation are eliminated.&lt;/li&gt;
&lt;li&gt;Improved extensibility and flexibility.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The delegation from the Entities to the Behaviors can degrade performance.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Real World Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The display of different image formats on different operating systems is a good example of the Bridge pattern. You might have different image abstractions for both jpeg and png images. The image structure is the same across all operating systems, but the how it's viewed (the implementation) is different on each OS. This is the type of decoupling that the Bridge pattern allows.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Software Examples
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UnifiedPOS or UPOS that provides vendor-neutral APIs for numerous Point Of Sale peripherals.&lt;/li&gt;
&lt;li&gt;OS specific Device Driver interfaces that define common standards for various devices.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>pattern</category>
      <category>java</category>
      <category>design</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Decode Adapter Pattern</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Fri, 26 Nov 2021 18:37:59 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/decode-adapter-pattern-2i4p</link>
      <guid>https://dev.to/gauravratnawat/decode-adapter-pattern-2i4p</guid>
      <description>&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To wrap an existing class with a new interface.&lt;/li&gt;
&lt;li&gt;To perform impedance matching&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Intent
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Target - defines the domain-specific interface that Client uses.&lt;/li&gt;
&lt;li&gt;Adapter - adapts the interface Adaptee to the Target interface.&lt;/li&gt;
&lt;li&gt;Adaptee - defines an existing interface that needs adapting.&lt;/li&gt;
&lt;li&gt;Client - collaborates with objects conforming to the Target interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Before&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5h0wlv3jkbquq00esps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5h0wlv3jkbquq00esps.png" alt="Adaptor before"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F166t6g4bytmx1mfwoqy9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F166t6g4bytmx1mfwoqy9.png" alt="Adaptor after"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;Assume that you have an e-commerce application which is serving your customers for a long time. This e-commerce application is using a Legacy Order Management System (OMS). Due to the high maintenance cost and degraded performance of the legacy OMS software, you have decided to use a cheap and efficient OMS software which is readily available in the market. However, you realize that the interfaces are different in the new software and it requires a lot of code change in the existing e-commerce application.&lt;/p&gt;

&lt;p&gt;Adapter design pattern can be very useful in these situations. Instead of modifying your e-commerce application to use the new interfaces, you can write a 'wrapper' class that acts as a bridge between your e-commerce application and the new OMS software. With this approach, the e-commerce application can still use the old interface.&lt;/p&gt;

&lt;p&gt;Adapter design pattern can be implemented in two ways. One using the inheritance method (Class Adapter) and second using the composition (Object Adapter). The following example depicts the implementation of Object adapter.&lt;/p&gt;

&lt;p&gt;1 Below is the code that uses the LegacyOMS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.adapter;

public class Item {
  private String name;
  private double price;

  public Item(String name, double price) {
    this.name = name;
    this.price = price;
  }

  public String getName() {
    return name;
  }

  public double getPrice() {
    return price;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.adapter;

public class Payment {

  public String type;
  public double amount;

  public Payment(String type, double amount) {
    super();
    this.type = type;
    this.amount = amount;
  }

  public void pay() {
    System.out.println(type + " " + amount + "$");
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.adapter;

import java.util.ArrayList;
import java.util.List;

public class LegacyOMS {

  /* The Legacy OMS accepts input in XML format */

  List cart = new ArrayList();
  List payments = new ArrayList();

  public void addItem(Item itemXml) {
    cart.add(itemXml);
    System.out.println(itemXml.getName() + " " + itemXml.getPrice());
  }

  public void makePayment(Payment paymentXml) {
    payments.add(paymentXml);
    paymentXml.pay();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 The client code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.client;

import com.gaurav.adapter.Item;
import com.gaurav.adapter.OMSAdapter;
import com.gaurav.adapter.Payment;

public class AdapterClient {

  public static void main(String[] args) {

    /* Create an order and add items */

    LegacyOMS oms = new LegacyOMS();

    oms.addItem(new Item("Italian Pizza", 6.99));
    oms.addItem(new Item("Wine", 9.99));
    oms.addItem(new Item("Beer", 5.99));
    oms.addItem(new Item("Red Apple", 1.49));
    oms.addItem(new Item("Almonds", 11.99));

    System.out.println("---------------------------------");
    /* Create payment and make payment */
    oms.makePayment(new Payment("CASH", 20.00));
    oms.makePayment(new Payment("CREDIT", 10.00));
    oms.makePayment(new Payment("DEBIT", 10.00));
    System.out.println("---------------------------------");

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

&lt;/div&gt;



&lt;p&gt;3 When the OMS needs to be swapped, you can simply create an Adapter class with same interface that the client uses. This adapter/wrapper class "maps" the client interface to the adaptee (New OMS) interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.adapter;

import java.util.ArrayList;
import java.util.List;

public class NewOMS {

  /* The new OMS accepts input in JSON format */

  List cart = new ArrayList();
  List payments = new ArrayList();

  public void addToBasket(Item itemJson) {
    cart.add(itemJson);
    System.out.println(itemJson.getName() + " " + itemJson.getPrice());
  }

  public void pay(Payment paymentJson) {
    payments.add(paymentJson);
    paymentJson.pay();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.adapter;

public class OMSAdapter {

  /* Object Adapter uses composition */
  private NewOMS newOMS;

  public OMSAdapter() {
    newOMS = new NewOMS();
  }

  public void addItem(Item item) {
    convertXmlToJson(item);
    newOMS.addToBasket(item);
  }

  public void makePayment(Payment p) {
    convertXmlToJson(p);
    newOMS.pay(p);
  }

  /* The new OMS accepts only Json input.
   * Convert the client requests from XML to Json*/
  private void convertXmlToJson(Object o) {
    System.out.println("Converted from XML to JSON");
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4 The new client code. The client interacts in the same way as before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.client;

import com.gaurav.adapter.Item;
import com.gaurav.adapter.OMSAdapter;
import com.gaurav.adapter.Payment;

public class AdapterClient {

  public static void main(String[] args) {

    /* Create an order and add items */

    //LegacyOMS oms = new LegacyOMS();
    /* Use Adapter class with the same interface */
    OMSAdapter oms = new OMSAdapter();

    oms.addItem(new Item("Italian Pizza", 6.99));
    oms.addItem(new Item("Wine", 9.99));
    oms.addItem(new Item("Beer", 5.99));
    oms.addItem(new Item("Red Apple", 1.49));
    oms.addItem(new Item("Almonds", 11.99));

    System.out.println("---------------------------------");
    /* Create payment and make payment */
    oms.makePayment(new Payment("CASH", 20.00));
    oms.makePayment(new Payment("CREDIT", 10.00));
    oms.makePayment(new Payment("DEBIT", 10.00));
    System.out.println("---------------------------------");

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[output]
Italian Pizza   6.99
Wine            9.99
Beer            5.99
Red Apple       1.49
Almonds        11.99
---------------------------------
CASH    20.0$
CREDIT  10.0$
DEBIT   10.0$
---------------------------------

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Class adapter can override adaptee's behavior.&lt;/li&gt;
&lt;li&gt;Objects adapter allows a single adapter to work with many adaptees.&lt;/li&gt;
&lt;li&gt;Helps achieve reusability and flexibility.&lt;/li&gt;
&lt;li&gt;Client class is not complicated by having to use a different interface and can use polymorphism to swap between different implementations of adapters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Object adapter involves an extra level of indirection.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real World Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Power adapters&lt;/li&gt;
&lt;li&gt;Memory card adapters&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Software Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Wrappers used to adopt 3rd parties libraries and frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Java SDK Examples
&lt;/h4&gt;

&lt;p&gt;java.util.Arrays asList()&lt;br&gt;
java.util.Collections list()&lt;br&gt;
java.util.Collections enumeration()&lt;br&gt;
java.io.InputStreamReader(InputStream) (returns a Reader)&lt;br&gt;
java.io.OutputStreamWriter(OutputStream) (returns a Writer)&lt;/p&gt;

&lt;p&gt;Want to discuss more &lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/gauravratnawat" rel="noopener noreferrer"&gt;Lets have a Coffee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pattern</category>
      <category>java</category>
      <category>design</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Decode Singleton Pattern</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Sun, 14 Nov 2021 05:57:15 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/decode-singleton-pattern-27h1</link>
      <guid>https://dev.to/gauravratnawat/decode-singleton-pattern-27h1</guid>
      <description>&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Application needs “only one instance” of a class.&lt;/li&gt;
&lt;li&gt;To have complete control over the instance creation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Intent
&lt;/h3&gt;

&lt;p&gt;Ensure a class has only one instance, and provide a global point of access to it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Singleton Class&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

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




&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;Create a Singleton class with a static instance and a private constructor. Provide a static method to allow access to this 'only' instance.&lt;/p&gt;

&lt;p&gt;1 Create a Singleton Class &lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.singleton;

public class Singleton {

  /* the singleton obj */
  private static Singleton instance = null;

  /* private constructor to avoid
     external instantiation of this class */
  private Singleton() {
  }

  /* method to get the singleton obj */
  public static Singleton getInstance() {
    if (instance == null) {
      synchronized (Singleton.class) {
        /* double checked locking */
        if (instance == null) {
          instance = new Singleton();
        }
      }
    }
    return instance;
  }

  public void printObj() {
    System.out.println("Unique Id of the obj: "
    + System.identityHashCode(this));
  }

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

&lt;/div&gt;



&lt;p&gt;2 Access the singleton instance &lt;br&gt;
&lt;/p&gt;

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

  public static void main(String[] args) {
    Singleton obj1 = Singleton.getInstance();
    obj1.printObj();
    Singleton obj2 = Singleton.getInstance();
    obj2.printObj();
  }

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unique Id of the obj: 1916222108
Unique Id of the obj: 1916222108
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Controlled instantiation&lt;/li&gt;
&lt;li&gt;Supports both EAGER and LAZY initializations&lt;/li&gt;
&lt;li&gt;Singletons can be converted to Multitons (to support limited number of instances identified by keys)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Singleton is often seen as 'not-so-good' design as it resembles global variables&lt;/li&gt;
&lt;li&gt;Special handling is required if the Singleton object needs to be deleted&lt;/li&gt;
&lt;li&gt;Singletons that maintain global state may cause issues&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Real World Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Office of the President (there can be only one President at any given time)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Software Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Logger classes&lt;/li&gt;
&lt;li&gt;Window Manager&lt;/li&gt;
&lt;li&gt;Printer Spooler&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Java SDK Examples
&lt;/h4&gt;

&lt;p&gt;java.lang.Runtime.getRuntime( )&lt;br&gt;
java.awt.Toolkit.getDefaultToolkit( )&lt;br&gt;
java.awt.Desktop.getDesktop( )&lt;br&gt;
java.util.logging.LogManager.getLogManager( )&lt;br&gt;
java.lang.System#getSecurityManager( )&lt;/p&gt;




&lt;p&gt;Want to discuss more &lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/gauravratnawat" rel="noopener noreferrer"&gt;Lets have a Coffee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pattern</category>
      <category>java</category>
      <category>design</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Select Right Aurora DB Instance 😎</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Wed, 03 Nov 2021 12:39:04 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/select-right-aurora-db-instance-56l1</link>
      <guid>https://dev.to/gauravratnawat/select-right-aurora-db-instance-56l1</guid>
      <description>&lt;h2&gt;
  
  
  The Factors
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Back of envelope calculation for storage required (based on inputs from product requirements) . Aurora scales automatically so less of an issue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read scaling -  Back of envelope no calculation for # of reads per sec -  can be handled by adding read replicas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write scaling -  In single-primary mode - there is a single writer DB . This can be the main factor for choosing the db instance. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Estimate the number of write connections needed per second . and pick the db instance based on the connection limits (keeping a factor for connection pooling) -&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also a guesstimate for the working set of data needed to be pulled into the memory for things like sorting/filtering etc will be a factor. The limits are mentioned in the above page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This can only be a starting point . You should prioritise perf testing at a time your app is relatively stable to benchmark semi-realworld load.  More often than not perf is constraint than storage.&lt;br&gt;
(also benchmark reports in aws are highly optimistic, you mostly will not be able to achieve these results in your environment)&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Managing.html#AuroraPostgreSQL.Managing.MaxConnections"&gt;AWS&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;em&gt;An example of how we approached (Simplified)&lt;/em&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Back of the envelope calculation for storage
&lt;/h4&gt;

&lt;p&gt;Assuming we will have total 10,00,000 users .&lt;br&gt;
Each user record in DB will have - at max 10 fields.&lt;br&gt;
Each field = max 1 kb (1000char) =&amp;gt; Each User record = 10kb&lt;br&gt;
So Total storage needed = 10,00,000 kb = 10 GB&lt;/p&gt;

&lt;h4&gt;
  
  
  Read/Write Ratio/concurrency
&lt;/h4&gt;

&lt;p&gt;The DB will be read heavy database. A customer will change password may be once a month but login multiple times.&lt;/p&gt;

&lt;p&gt;DocumentDB tops out at a maximum database size of 64TB and 4,500 concurrent connections per instance. DocumentDB supports a single primary node for writes and up to 15 replicas within a single Amazon region.That means with 15 replicas DocumentDB can handle 15 * 4500(max) = 67500 concurrent connection.That means some connections will be waiting in the connection pool.However , these limits may be adjusted - we need to check with AWS.&lt;/p&gt;




</description>
      <category>aws</category>
      <category>devops</category>
      <category>database</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Decode Prototype Pattern</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Wed, 03 Nov 2021 12:24:59 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/decode-prototype-pattern-589</link>
      <guid>https://dev.to/gauravratnawat/decode-prototype-pattern-589</guid>
      <description>&lt;p&gt;Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To improve the performance when object creation is costly and time consuming.&lt;/li&gt;
&lt;li&gt;To simplify and optimize multiple objects creation that will have mostly the same data&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Intent
&lt;/h3&gt;

&lt;p&gt;Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.&lt;/p&gt;




&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;p&gt;A class that implements Cloneable interface (public)&lt;/p&gt;




&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A8mw_jDp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bkkklvavqnbfx50x9ba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A8mw_jDp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bkkklvavqnbfx50x9ba.png" alt="Prototype" width="197" height="309"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;Most of the cloud platforms behave like Prototype pattern to create instances quickly upon requests. This is achieved with the help of pre-installed Machine Images. When a customer wants a Windows or Linux instance, the cloud software just loads the already created machine image on to a server hardware (rather than going through the complete installation process). This saves a lot of time.&lt;/p&gt;

&lt;p&gt;1 Create a base machine image by installing the specified OS and antivirus software. Provide a 'clone' method so that client can create an object without using a time consuming 'new' operator every time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.prototype;

public class MachineImage implements Cloneable {

  StringBuilder image;

  public MachineImage(String os, String antivirusSW) {
    image = new StringBuilder();
    image.append(os)
         .append(" + " + antivirusSW);
  }

  private MachineImage(String sw) {
    image = new StringBuilder(sw);
  }

  public void install(String sw) {
    image.append(sw);
  }

  public void printSw() {
    System.out.println(image);
  }

  @Override
  public MachineImage clone()
      throws CloneNotSupportedException {
    return new MachineImage(this.image.toString());
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 The client code. The client creates a base image and clones it to create other images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.client;

import com.gaurav.prototype.MachineImage;

public class PrototypeClient {
  public static void main(String [] args)
      throws CloneNotSupportedException {

    /* Create base Machine Images */
    MachineImage linuxVM= new MachineImage("Linux", "Symantec");
    MachineImage windowsVM = new MachineImage("Windows", "MaAfee");

    /* Clone Linux VM and Install Web Server */
    MachineImage webServer= linuxVM.clone();
    webServer.install(" + Web Server S/W");

    /* Create a copy of the Web Server and
     * install Application server on top of it */
    MachineImage webAppServer = webServer.clone();
    webAppServer.install(" + App Server S/W");

    /* Clone Linux VM and Install DB Server */
    MachineImage dbServer= linuxVM.clone();
    dbServer.install(" + Database Server S/W");

    /* Create a test machine from Windows Image */
    MachineImage testMachine= windowsVM.clone();

    System.out.print("Web Server Configuration: ");
    webServer.printSw();
    System.out.print("App Server Configuration: ");
    webAppServer.printSw();
    System.out.print("DB Server Configuration: ");
    dbServer.printSw();
    System.out.print("Test Machine Configuration: ");
    testMachine.printSw();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[output]
Web Server Configuration: Linux OS + Antivirus S/W + Web Server S/W
App Server Configuration: Linux OS + Antivirus S/W + Web Server S/W + App Server S/W
DB Server Configuration: Linux OS + Antivirus S/W + Database Server S/W
Test Machine Configuration: Linux OS + Antivirus S/W
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Performance: Cloning (using MemberwiseClone) is considerably less expensive than creating a new object afresh (with new operator).&lt;/li&gt;
&lt;li&gt;Objects can be cloned very dynamically, without any insistence on up-front instantiation. The first created object can be created at any time in the application execution, and further duplication can take place at any time ahead.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Deep copy has to be handled carefully.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Real World Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Biological Cell splitting&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Software Examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Virtual Machine Images - Have one image per OS which has all the required s/w installed.&lt;/li&gt;
&lt;li&gt;DVD duplication - Duplication of the master dvd to create several copies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Java SDK Examples
&lt;/h4&gt;

&lt;p&gt;java.lang.Object clone()&lt;/p&gt;




&lt;h4&gt;
  
  
  Hope you like it. Would love to hear your thoughts on this design pattern.
&lt;/h4&gt;

&lt;p&gt;Want to discuss more &lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/gauravratnawat"&gt;Lets have a Coffee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>design</category>
      <category>architecture</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>Decode Factory Pattern</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Sun, 24 Oct 2021 05:40:41 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/decode-factory-pattern-245m</link>
      <guid>https://dev.to/gauravratnawat/decode-factory-pattern-245m</guid>
      <description>&lt;p&gt;Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To avoid dealing with inconsistent object when the object needs to be created over several steps.&lt;/li&gt;
&lt;li&gt;To avoid too many constructor arguments.&lt;/li&gt;
&lt;li&gt;To construct an object that should be immutable.&lt;/li&gt;
&lt;li&gt;To encapsulate the complete creation logic.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Intent
&lt;/h3&gt;

&lt;p&gt;Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.&lt;/p&gt;




&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;An Interface (or) Abstract class (public)&lt;/li&gt;
&lt;li&gt;Set of implementation subclasses (private)&lt;/li&gt;
&lt;li&gt;A Factory Method (public)&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ukqhsifi4sxhobbiouq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ukqhsifi4sxhobbiouq.png" alt="Factory Method Pattern"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;1 Create an interface. Clients can code for this interface without worrying about the internal implementation..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.factorymethod;

public interface Vehicle {
  void design();
  void manufacture();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 Create a set of implementation subclasses. Constructors are protected to prohibit instantiations in clients modules using the 'new' operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.factorymethod;

public class Car implements Vehicle {

  Car() {
    /* constructor is protected.
       clients need to use the factory method */
  }

  @Override
  public void design() {
    System.out.println("Designing Car");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Car");
  }

}

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.factorymethod;

public class Truck implements Vehicle {

  Truck() {
    /* constructor is protected.
       clients need to use the factory method */
  }

  @Override
  public void design() {
    System.out.println("Designing Truck");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Truck");
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.factorymethod;

public class Motorcycle implements Vehicle {

  Motorcycle() {
    /* constructor is protected.
       clients need to use the factory method */
  }

  @Override
  public void design() {
    System.out.println("Designing Motorcycle");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Motorcycle");
  }

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

&lt;/div&gt;



&lt;p&gt;3 Create a class with method 'getVehicle()'. Clients can use this method to create an object instead of using 'new' operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.factorymethod;

public class VehicleFactory {

  /* This is the factory method exposed to the client.
     Client requests for an object by passing the type.
     Client does not need to know about which &amp;amp; how object
     is created internally.
     */
  public Vehicle getVehicle(String vehicleType)
      throws VehicleTypeNotFoundException {

    if (vehicleType == null) {
      return null;
    }

    Vehicle vehicle = null;

    switch (vehicleType) {
      case "car":
        vehicle = new Car();
        break;
      case "truck":
        vehicle = new Truck();
        break;
      case "motorcycle":
        vehicle = new Motorcycle();
        break;
      default:
        throw new VehicleTypeNotFoundException();
    }

    return vehicle;
  }

}

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

&lt;/div&gt;



&lt;p&gt;4 The client code. Client knows only the factory method and the interface. Client code does not use 'new' hence decoupled from implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.client;

import java.util.Scanner;

import com.gaurav.factorymethod.Vehicle;
import com.gaurav.factorymethod.VehicleFactory;
import com.gaurav.factorymethod.VehicleTypeNotFoundException;

public class FactoryMethodClient {

  public static void main(String[] args) {

    Scanner in = new Scanner(System.in);
    String vehicleType = in.nextLine().toLowerCase();

    /* Create a factory instance */
    VehicleFactory factory = new VehicleFactory();

    try {

      /* Create an appropriate vehicle based on the input */
      Vehicle vehicle = factory.getVehicle(vehicleType);

      /* Design and manufacture the vehicle */
      vehicle.design();
      vehicle.manufacture();

    } catch (VehicleTypeNotFoundException e) {
      System.out.println("Invalid vehicle type entered!");
    }

    in.close();
  }

}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[input1]
    MotorCycle
[output1]
    Designing Motorcycle
    Manufacturing Motorcycle

[input2]
    Car
[output2]
    Designing Car
    Manufacturing Car

[input3]
    Bus
[output3]
    Invalid vehicle type entered!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Loose coupling allows changing the internals without impacting the customer code&lt;/li&gt;
&lt;li&gt;Factory method provides a single point of control for multiple products&lt;/li&gt;
&lt;li&gt;Number of instances and their reusability can be controlled with Singleton or Multiton&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;p&gt;An extra level of abstraction makes the code more difficult to read.&lt;/p&gt;




&lt;h3&gt;
  
  
  Real World Examples
&lt;/h3&gt;

&lt;p&gt;Renting Vehicles. Customer needs to specify only the type of vehicle (car, truck, etc.) that is needed. Customer need not know about the internal details of the vehicle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Example
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Memcache&lt;/li&gt;
&lt;li&gt;Filecache&lt;/li&gt;
&lt;li&gt;Code for SQL standard without worrying about the underlying DB&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Java SDK Examples
&lt;/h4&gt;

&lt;p&gt;java.util.Calendar.getInstance()&lt;br&gt;
java.util.ResourceBundle.getBundle()&lt;br&gt;
java.text.NumberFormat.getInstance()&lt;br&gt;
java.nio.charset.Charset.forName()&lt;br&gt;
java.util.EnumSet.of()&lt;br&gt;
javax.xml.bind.JAXBContext.createMarshaller()&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;a href="https://stackoverflow.com/questions/1001767/what-is-the-basic-difference-between-the-factory-and-abstract-factory-design-pat" rel="noopener noreferrer"&gt;Difference between Abstract factory and Factory pattern?&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;TS;MR:&lt;br&gt;
The Abstract Factory is a set of Factory Methods.&lt;/p&gt;

&lt;p&gt;TL;DR:&lt;br&gt;
With the Factory pattern, you produce instances of implementations (Apple, Banana, Cherry, etc.) of a particular interface -- say, IFruit.&lt;/p&gt;

&lt;p&gt;With the Abstract Factory pattern, you provide a way for anyone to provide their own factory. This allows your warehouse to be either an IFruitFactory or an IJuiceFactory, without requiring your warehouse to know anything about fruits or juices. &lt;/p&gt;




&lt;h4&gt;
  
  
  Hope you like it. Would love to hear your thoughts on this design pattern.
&lt;/h4&gt;

&lt;p&gt;Want to discuss more &lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/gauravratnawat" rel="noopener noreferrer"&gt;Lets have a Coffee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>design</category>
      <category>architecture</category>
      <category>java</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>Disaster Recovery Maturity Model</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Fri, 22 Oct 2021 20:01:21 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/disaster-recovery-maturity-model-1f69</link>
      <guid>https://dev.to/gauravratnawat/disaster-recovery-maturity-model-1f69</guid>
      <description>&lt;h1&gt;
  
  
  Points to be consider while setting up DRMM.
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Catalog your applications:
&lt;/h3&gt;

&lt;p&gt;Make sure you are aware of all applications that exist in the ecosystem and that they have assigned owners along with their contact information. Also, make sure that the application owner is made aware of their responsibilities E.g. in case of an emergency, they or whoever they nominate on their behalf may be contacted for remediation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Document standard recovery procedures:
&lt;/h3&gt;

&lt;p&gt;For each application, make sure recovery procedures are documented and more importantly, well understood&lt;br&gt;
Define a strategy: Make sure that the RPO and RTO for each application is defined i.e. a backup is defined.&lt;/p&gt;

&lt;h3&gt;
  
  
  Categorize applications into resilience categories:
&lt;/h3&gt;

&lt;p&gt;Not all applications are created equal. Define resilience categories and slot each application into one of them. For e.g. the payments application for a credit card company may be more important to recover than a reporting application. Be aware of legal and compliance regulations for your domain. DR strategies come at a cost. An active-active deployment will likely cost more money than a cold standby. Make sure your business stakeholders are aware and participate actively in this categorisation process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practice!:
&lt;/h3&gt;

&lt;p&gt;Ideally all the time as part of your automated deployment pipeline. Take your DR drills seriously. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can you really recover if things start going south?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Automate!:
&lt;/h3&gt;

&lt;p&gt;Infra as Code, automated configuration and secrets management, automated deployment, 'nuff said!&lt;br&gt;
AWS' Well Architected Framework has a reliability pillar which talks about planning for disaster recovery that you may find useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do maturity Assessment:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Areas to consider for maturity assessment (AWS context):
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Applicable across all inventory -- application, network, infra, CI, storage, test-environments, etc. Any system that gets used today, needs a DR strategy -- including test systems, CI/CD, toggle/configuration stores, doc repos, etc.. because they ALL play an important role in keeping the Software running and Development process (machinery that creates software) running. (This is borrowed from Security thinking, where keeping non-Prod systems is very important too).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are components in one AZ, multi-AZ, or cross Region (is cross region level complexity needed?)&lt;br&gt;
For their business what are the RPO/RTO requirements? Each component then needs to be assessed against those goals -- to get a "heat map" for the whole inventory -- where are we today, vs where do we want to be, vs how will we get there, and what are the priorities? The RPO/RTO goals are usually not the same for all components, since some sub-systems are more critical than others.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is the level of automation (to support the RPO/RTO objectives)? &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How frequently is the automation tested?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do they have automation/checks in place that can detect new features/configurations that are no longer meeting RPO/RTO objectives, because DR/Backup/Restore scripts have become out-of-date/obsolete? ("DR Automation obsolescence drift"). Think Poka-Yokes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>distributedsystems</category>
      <category>disasterrecovery</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Decode Builder Design Pattern</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Mon, 18 Oct 2021 18:45:34 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/builder-pattern-2pk2</link>
      <guid>https://dev.to/gauravratnawat/builder-pattern-2pk2</guid>
      <description>&lt;p&gt;Separate the construction of a complex object from its representation so that the same construction process can create different representations.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To avoid dealing with inconsistent object when the object needs to be created over several steps.&lt;/li&gt;
&lt;li&gt;To avoid too many constructor arguments.&lt;/li&gt;
&lt;li&gt;To construct an object that should be immutable.&lt;/li&gt;
&lt;li&gt;To encapsulate the complete creation logic.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Intent
&lt;/h3&gt;

&lt;p&gt;Separate the construction of a complex object from its representation so that the same construction process can create different representations.&lt;/p&gt;




&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The Builder class specifies an abstract interface for creating parts of a Product object.&lt;/li&gt;
&lt;li&gt;The ConcreteBuilder constructs and puts together parts of the product by implementing the Builder interface. It defines and keeps track of the representation it creates and provides an interface for saving the product.&lt;/li&gt;
&lt;li&gt;The Director class constructs the complex object using the Builder interface.&lt;/li&gt;
&lt;li&gt;The Product represents the complex object that is being built.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SjAv4G4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bjply6jkt7f3sssw3du.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SjAv4G4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bjply6jkt7f3sssw3du.png" alt="Builder Pattern" width="601" height="568"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;1 Define the Product (House) that gets assembled in the builder pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.builder;

/* The house is the object that gets assembled in the builder pattern. */
public class House {

  private String floorType;
  private String wallType;
  private String roofType;

  public String getFloorType() {
    return floorType;
  }

  public void setFloorType(String floorType) {
    this.floorType = floorType;
  }

  public String getWallType() {
    return wallType;
  }

  public void setWallType(String wallType) {
    this.wallType = wallType;
  }

  public String getRoofType() {
    return roofType;
  }

  public void setRoofType(String roofType) {
    this.roofType = roofType;
  }

  public String toString() {
    return new String("\nConstructing House \n FloorType: " + floorType
        + "\n WallType:  " + wallType + "\n RoofType:  " + roofType );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 Define the Builder interface (or abstract class) along with Concrete Builders. The Builder interface contains methods for the step by step construction of the product. It also has a build method for retrieving the product object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.builder;

public interface HouseBuilder {

  public HouseBuilder buildFloor();
  public HouseBuilder buildWall();
  public HouseBuilder buildRoof();
  public House build();

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

&lt;/div&gt;



&lt;p&gt;3 Concrete Builders implement the Builder interface. A Concrete Builder is responsible for creating and assembling a Product object. Different Concrete Builders create and assemble Product objects differently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.builder;

public class ConcreteHouseBuilder implements HouseBuilder {

  private House house;

  public ConcreteHouseBuilder() {
    house = new House();
  }

  public HouseBuilder buildFloor() {
    house.setFloorType("concrete");
    return this;
  }

  public HouseBuilder buildWall() {
    house.setWallType("concrete");
    return this;
  }

  public HouseBuilder buildRoof() {
    house.setRoofType("concrete");
    return this;
  }

  public House build() {
    return house;
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.gaurav.builder;

public class WoodenHouseBuilder implements HouseBuilder {

  private House house;

  public WoodenHouseBuilder() {
    house = new House();
  }

  public HouseBuilder buildFloor() {
    house.setFloorType("wood");
    return this;
  }

  public HouseBuilder buildWall() {
    house.setWallType("wood");
    return this;
  }

  public HouseBuilder buildRoof() {
    house.setRoofType("wood");
    return this;
  }

  public House build() {
    return house;
  }

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

&lt;/div&gt;



&lt;p&gt;4 A Director object is responsible for constructing a Product. It does this via the Builder interface to a Concrete Builder. It constructs a Product via the various Builder methods. The director class ensures that all the required operations are performed before the object is returned to the client in a 'consistent' state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.builder;

public class HouseBuildDirector {
  private HouseBuilder builder;

  public HouseBuildDirector(final HouseBuilder builder) {
    this.builder = builder;
  }

  public House construct() {
    /* call the necessary methods and return the consistent object*/
    return builder.buildFloor().buildWall().buildRoof().build();
  }

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

&lt;/div&gt;



&lt;p&gt;5 The client code. The Client uses different builder objects to create different types of products. However, the construction process is same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.client;

import com.gaurav.builder.ConcreteHouseBuilder;
import com.gaurav.builder.HouseBuildDirector;
import com.gaurav.builder.HouseBuilder;
import com.gaurav.builder.WoodenHouseBuilder;

public class BuilderClient {

  public static void main(final String[] arguments) {

    /* Construct a concrete house */
    HouseBuilder builder = new ConcreteHouseBuilder();
    HouseBuildDirector carBuildDirector = new HouseBuildDirector(builder);
    System.out.println(carBuildDirector.construct());

    /* Construct a wooden house */
    builder = new WoodenHouseBuilder();
    carBuildDirector = new HouseBuildDirector(builder);
    System.out.println(carBuildDirector.construct());
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Output
Constructing House 
 FloorType: concrete
 WallType:  concrete
 RoofType:  concrete

Constructing House 
 FloorType: wood
 WallType:  wood
 RoofType:  wood
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Construction process can be controlled by the director.&lt;/li&gt;
&lt;li&gt;Useful when many operations have to be done to build an object.&lt;/li&gt;
&lt;li&gt;Avoids Telescoping Constructor Pattern.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;p&gt;Not suitable if a mutable object is required.&lt;/p&gt;




&lt;h3&gt;
  
  
  Real World Examples
&lt;/h3&gt;

&lt;p&gt;Building a house - We need to tell the architect what all we want as part of the building. The Architect then designs and constructs the building. It will be handed over only when everything is implemented. We do not get a 'partially' built house (which is unsafe).&lt;/p&gt;

&lt;h4&gt;
  
  
  Java SDK Examples
&lt;/h4&gt;

&lt;p&gt;java.lang.StringBuilder append()&lt;br&gt;
java.lang.StringBuffer append()&lt;br&gt;
java.nio.ByteBuffer put()&lt;br&gt;
javax.swing.GroupLayout.Group addComponent()&lt;br&gt;
java.lang.Appendable implementations&lt;/p&gt;




&lt;h4&gt;
  
  
  Hope you like it. Would love to hear your thoughts on this design pattern.
&lt;/h4&gt;

</description>
      <category>java</category>
      <category>architecture</category>
      <category>design</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>Decode Abstract Factory Design Pattern</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Sun, 17 Oct 2021 19:38:03 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/abstract-factory-haf</link>
      <guid>https://dev.to/gauravratnawat/abstract-factory-haf</guid>
      <description>&lt;p&gt;Provide an interface for creating families of related or dependent objects without specifying their concrete classes.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To support families of related or dependent objects.&lt;/li&gt;
&lt;li&gt;To encapsulate platform dependencies to make an application portable.&lt;/li&gt;
&lt;li&gt;To prevent client code from using the 'new' operator.&lt;/li&gt;
&lt;li&gt;To easily swap the underlying platform with minimal changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Intent
&lt;/h3&gt;

&lt;p&gt;Provide an interface for creating families of related or dependent objects without specifying their concrete classes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;An Abstract Factory class (public)&lt;/li&gt;
&lt;li&gt;Factory Implementations for various familes (protected)&lt;/li&gt;
&lt;li&gt;Interfaces for various products (public)&lt;/li&gt;
&lt;li&gt;Set of product implementations for various families (protected)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;1 Define interfaces for different types products/objects. Each family will have all these parts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.abstractfactory;

public interface Engine {

  public void design();
  public void manufacture();
  public void test();

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.abstractfactory;

public interface Tyre {

  public void design();
  public void manufacture();

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

&lt;/div&gt;



&lt;p&gt;2 Create sets of implementation subclasses for the above interfaces. Classes are access protected to prohibit instantiations in client modules using the 'new' operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.abstractfactory;

class CarEngine implements Engine {

  @Override
  public void design() {
    System.out.println("Designing Car Engine");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Car Engine");
  }

  @Override
  public void test() {
    System.out.println("Testing Car Engine");
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.abstractfactory;

class TruckEngine implements Engine {

  @Override
  public void design() {
    System.out.println("Designing Truck Engine");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Truck Engine");
  }

  @Override
  public void test() {
    System.out.println("Testing Truck Engine");
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.abstractfactory;

class CarTyre implements Tyre {

  @Override
  public void design() {
    System.out.println("Designing Car Tyre");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Car Tyre");
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.gaurav.abstractfactory;

class TruckTyre implements Tyre {

  @Override
  public void design() {
    System.out.println("Designing Truck Tyre");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Truck Tyre");
  }

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

&lt;/div&gt;



&lt;p&gt;3 Create a Abstract Factory class with factory method 'getFactory()'. Clients can use this method to get an object the required factory. This example uses both Singleton and Factory Method patterns for better design.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.abstractfactory;

public abstract class Factory {

  /* Singleton Factory objects */
  private static Factory carFactory = null;
  private static Factory truckFactory = null;

  public abstract Engine getEngine();
  public abstract Tyre getTyre();

  /*
   * This is the factory method exposed to the client.
   * Client requests for a factory instance by passing the type.
   * Client does not need to know about which &amp;amp; how
   * object is created internally.
   */
  public static Factory getFactory(String vehicleType)
      throws UnknownVehicleException {

    if (vehicleType == null) {
      return null;
    }

    Factory factory = null;
    switch (vehicleType) {
      case "car":
        if (carFactory == null)
          carFactory = new CarFactory();
        factory = carFactory;
        break;
      case "truck":
        if (truckFactory == null)
          truckFactory = new TruckFactory();
        factory = truckFactory;
        break;
      default:
        throw new UnknownVehicleException();
    }

    return factory;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4 Create Factory implementations. Classes are protected to prohibit direct access in client modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.abstractfactory;

class CarFactory extends Factory {

  @Override
  public Engine getEngine() {
    return new CarEngine();
  }

  @Override
  public Tyre getTyre() {
    return new CarTyre();
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package com.gaurav.abstractfactory;

public class TruckFactory extends Factory {

  TruckFactory() {}

  @Override
  public Engine getEngine() {
    return new TruckEngine();
  }

  @Override
  public Tyre getTyre() {
    return new TruckTyre();
  }

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

&lt;/div&gt;



&lt;p&gt;5 The client code. Client is exposed to only the Abstract Factory class and the interfaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.gaurav.client;

import java.util.Scanner;

import com.gaurav.abstractfactory.Engine;
import com.gaurav.abstractfactory.Factory;
import com.gaurav.abstractfactory.Tyre;
import com.gaurav.abstractfactory.UnknownVehicleException;

public class AbstractFactoryClient {

  public static void main(String[] args) {

    Scanner in = new Scanner(System.in);
    String vehicleType = in.nextLine().toLowerCase();

    /* Get the factory instance */
    Factory factory;
    try {
      factory = Factory.getFactory(vehicleType);

      /* Get the Engine from the factory */
      Engine engine = factory.getEngine();
      engine.design();
      engine.manufacture();
      engine.test();

      /* Get the Tyre from the factory */
      Tyre tyre = factory.getTyre();
      tyre.design();
      tyre.manufacture();

    } catch (UnknownVehicleException e) {
      System.out.println("Invalid vehicle type entered!");
    }

    in.close();
  }

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[input1]
    Car
[output1]
    Designing Car Engine
    Manufacturing Car Engine
    Testing Car Engine
    Designing Car Tyre
    Manufacturing Car Tyre

[input2]
    Bus
[output2]
    Invalid vehicle type entered!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Loosely coupled code.&lt;/li&gt;
&lt;li&gt;Abstract Factory provides a single point of access for all products in a family.&lt;/li&gt;
&lt;li&gt;New product family can be easily supported.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More layers of abstraction increases complexity.&lt;/li&gt;
&lt;li&gt;If there are any changes to any underlying detail of one factory, the interface might need to be modified for all the factories.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real World Examples
&lt;/h3&gt;

&lt;p&gt;Providing data access to two different data sources (e.g. a SQL Database and a XML file). You have two different data access classes (a gateway to the datastore). Both inherit from a base class that defines the common methods to be implemented (e.g. Load, Save, Delete). Which data source shall be used shouldn't change the way client code retrieves it's data access class. Your Abstract Factory knows which data source shall be used and returns an appropriate instance on request. The factory returns this instance as the base class type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Examples
&lt;/h3&gt;

&lt;p&gt;Dependency Injection&lt;/p&gt;

&lt;h4&gt;
  
  
  Java SDK Examples
&lt;/h4&gt;

&lt;p&gt;javax.xml.parsers.DocumentBuilderFactory newInstance()&lt;br&gt;
javax.xml.transform.TransformerFactory newInstance()&lt;br&gt;
javax.xml.xpath.XPathFactory newInstance()&lt;/p&gt;

&lt;h4&gt;
  
  
  Hope you like it. Would love to hear your thoughts on this design pattern.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/gauravratnawat" rel="noopener noreferrer"&gt;Lets have a Coffee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>design</category>
      <category>architecture</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>Future Of Lombok</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Thu, 25 Mar 2021 07:06:54 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/future-of-lombok-g22</link>
      <guid>https://dev.to/gauravratnawat/future-of-lombok-g22</guid>
      <description>&lt;p&gt;Following the general release of JDK 16: &lt;a href="https://jdk.java.net/16/"&gt;https://jdk.java.net/16/&lt;/a&gt; and&lt;br&gt;
specially &lt;a href="https://openjdk.java.net/jeps/396"&gt;https://openjdk.java.net/jeps/396&lt;/a&gt; Lombok has severe build&lt;br&gt;
issues due to its reliance on the JDK internals which 16 has closed off,&lt;br&gt;
discussion here:&lt;br&gt;
&lt;a href="https://github.com/rzwitserloot/lombok/issues/2681"&gt;https://github.com/rzwitserloot/lombok/issues/2681&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Given the fact that Java 16 brings Records out of preview and libs like&lt;br&gt;
Lombok (over)relying on internal JDK functions, does it make sense to&lt;br&gt;
use Lombok in our code anymore?&lt;/p&gt;

&lt;p&gt;Java Records don't require any additional dependency, so it's better to use them instead of Lombok I think.&lt;/p&gt;

&lt;p&gt;If your project supports Java 14 you can already use them in Eclipse.&lt;br&gt;
There's a plugin in the marketplace for it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marketplace.eclipse.org/content/java-14-support-eclipse-2020-03-415"&gt;https://marketplace.eclipse.org/content/java-14-support-eclipse-2020-03-415&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lombok way&lt;br&gt;
Add lombok annotations on top of the class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public class TransactionLombok {
    private final String from;
    private final String to;
    private final int amount;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A constructor with all arguments and getters are generated by lombok.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TransactionLombok transactionLombok = new TransactionLombok("you", "me", 100);
assertThat(transactionLombok.getFrom()).isEqualTo("you");
assertThat(transactionLombok.getTo()).isEqualTo("me");
assertThat(transactionLombok.getAmount()).isEqualTo(100);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Records way&lt;br&gt;
Define a record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;record TransactionRecord(String from, String to, int amount) {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get constructor and getters by default in a record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TransactionRecord transactionRecord = new TransactionRecord("you", "me", 100);
assertThat(transactionRecord.from()).isEqualTo("you");
assertThat(transactionRecord.to()).isEqualTo("me");
assertThat(transactionRecord.amount()).isEqualTo(100);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see the new record keyword does the same job in a much neater way.&lt;br&gt;
Anything more?&lt;br&gt;
Yes, records can do more than that. It also provides the equals, hashCode and toString automatically for you. So this works as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assertThat(transactionRecord.equals(anotherTransactionRecord)).isTrue();
assertThat(transactionRecord.hashCode()).isEqualTo(anotherTransactionRecord.hashCode());
assertThat(transactionRecord.toString()).isEqualTo("TransactionRecord[from=you, to=me, amount=100]");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While in lombok you have to achieve the same thing by adding a few more annotations like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ToString
@EqualsAndHashCode
@AllArgsConstructor
@Getter
public class TransactionLombok {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or just make it a value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Value
public class TransactionLombok {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the record keyword can be considered as an equivalent to lombok’s &lt;code&gt;@Value&lt;/code&gt; annotation.&lt;br&gt;
Customized constructor&lt;br&gt;
In addition, records also supports customized constructors like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public TransactionRecord(String from, String to) {
    this(from, to, 0);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you want to validate the arguments, it’s also possible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public TransactionRecord {
    Objects.requireNonNull(from);
    Objects.requireNonNull(to);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Can records replace lombok?&lt;br&gt;
No.&lt;/em&gt;&lt;br&gt;
Even though records provides a lot of nice features and is neat in code, lombok still has way more features than records. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Builder
@With
public class TransactionLombok {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Records just don’t provide builder and clone functions. Therefore lombok will most probably coexist with records for long time.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>java</category>
      <category>lombook</category>
    </item>
    <item>
      <title>What's inside a container?</title>
      <dc:creator>Gaurav</dc:creator>
      <pubDate>Mon, 08 Jun 2020 10:15:45 +0000</pubDate>
      <link>https://dev.to/gauravratnawat/what-s-inside-a-container-5g03</link>
      <guid>https://dev.to/gauravratnawat/what-s-inside-a-container-5g03</guid>
      <description>&lt;p&gt;Hi People&lt;br&gt;
This is my first post on Dev.to&lt;br&gt;
Nowadays everyone is using containerized solution for CI/CD.&lt;br&gt;
I always wonder what makes a container to run in a host machine as a separate process/CPU/memory all along.&lt;/p&gt;

&lt;p&gt;So here are some of my findings:&lt;/p&gt;
&lt;h2&gt;
  
  
  Processes
&lt;/h2&gt;

&lt;p&gt;Containers are just normal Linux Processes with additional configuration applied. Launch the following Redis container so we can see what is happening under the covers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; docker run -d --name=db redis:alpine 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ilqt2f8mztuhy318ad4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ilqt2f8mztuhy318ad4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Docker container launches a process called redis-server. From the host, we can view all the processes running, including those started by Docker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ps aux | grep redis-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg97ko4hfs7cnu2j7bgdi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg97ko4hfs7cnu2j7bgdi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker can help us identify information about the process including the PID (Process ID) and PPID (Parent Process ID) via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker top db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqaby2xmx5ry2hzveajsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqaby2xmx5ry2hzveajsk.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Who is the PPID? Use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ps aux | grep &amp;lt;ppid&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to find the parent process. Likely to be Containerd.&lt;/p&gt;

&lt;p&gt;The command pstree will list all of the sub processes. See the Docker process tree using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pstree -c -p -A $(pgrep dockerd)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffyd2dhtfr1359fl9qjar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffyd2dhtfr1359fl9qjar.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, from the viewpoint of Linux, these are standard processes and have the same properties as other processes on our system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process Directory
&lt;/h2&gt;

&lt;p&gt;Linux is just a series of magic files and contents, this makes it fun to explore and navigate to see what is happening under the covers, and in some cases, change the contents to see the results.&lt;/p&gt;

&lt;p&gt;The configuration for each process is defined within the /proc directory. If you know the process ID, then you can identify the configuration directory.&lt;/p&gt;

&lt;p&gt;The command below will list all the contents of /proc, and store the Redis PID for future use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DBPID=$(pgrep redis-server)
echo Redis is $DBPID
ls /proc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each process has it's own configuration and security settings defined within different files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls /proc/$DBPID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fexfkjd7597l075lw9yyd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fexfkjd7597l075lw9yyd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
For example, you can view and update the environment variables defined to that process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/$DBPID/environ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9udcgh30kz8vi16ujuy3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9udcgh30kz8vi16ujuy3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it db env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Namespaces
&lt;/h2&gt;

&lt;p&gt;One of the fundamental parts of a container is namespaces. The concept of namespaces is to limit what processes can see and access certain parts of the system, such as other network interfaces or processes.&lt;/p&gt;

&lt;p&gt;When a container is started, the container runtime, such as Docker, will create new namespaces to sandbox the process. By running a process in it's own Pid namespace, it will look like it's the only process on the system.&lt;/p&gt;

&lt;p&gt;The available namespaces are:&lt;/p&gt;

&lt;p&gt;Mount (mnt)&lt;br&gt;
Process ID (pid)&lt;br&gt;
Network (net)&lt;br&gt;
Interprocess Communication (ipc)&lt;br&gt;
UTS (hostnames)&lt;br&gt;
User ID (user)&lt;br&gt;
Control group (cgroup)&lt;/p&gt;

&lt;p&gt;More information at &lt;a href="https://en.wikipedia.org/wiki/Linux_namespaces" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Linux_namespaces&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unshare can launch "contained" processes.&lt;br&gt;
Without using a runtime such as Docker, a process can still operate within it's own namespace. One tool to help is unshare.&lt;/p&gt;

&lt;p&gt;unshare --help&lt;/p&gt;

&lt;p&gt;With unshare it's possible to launch a process and have it create a new namespace, such as Pid. By unsharing the Pid namespace from the host, it looks like the bash prompt is the only process running on the machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo unshare --fork --pid --mount-proc bash
ps
exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fka916skjqgwqca59j0v7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fka916skjqgwqca59j0v7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
What happens when we share a namespace?&lt;br&gt;
Under the covers, Namespaces are inode locations on disk. This allows for processes to shared/reused the same namespace, allowing them to view and interact.&lt;/p&gt;

&lt;p&gt;List all the namespaces with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -lha /proc/$DBPID/ns/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F24poxc0y3zodaobdpdvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F24poxc0y3zodaobdpdvu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Another tool, NSEnter is used to attach processes to existing Namespaces. Useful for debugging purposes.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nsenter --target $DBPID --mount --uts --ipc --net --pid ps aux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj2gtvpmb87ltqmr6hvbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fj2gtvpmb87ltqmr6hvbg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
With Docker, these namespaces can be shared using the syntax container:. For example, the command below will connect nginx to the DB namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name=web --net=container:db nginx:alpine
WEBPID=$(pgrep nginx | tail -n1)
echo nginx is $WEBPID
cat /proc/$WEBPID/cgroup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhl46ydgmlmag8unuvrig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhl46ydgmlmag8unuvrig.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
While the net has been shared, it will still be listed as a namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -lha /proc/$WEBPID/ns/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the net namespace for both processes points to the same location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -lha /proc/$WEBPID/ns/ | grep net 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -lha /proc/$DBPID/ns/ | grep net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe0ayxifrtnfonbrxymm4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe0ayxifrtnfonbrxymm4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Chroot
&lt;/h2&gt;

&lt;p&gt;An important part of a container process is the ability to have different files that are independent of the host. This is how we can have different Docker Images based on different operating systems running on our system.&lt;/p&gt;

&lt;p&gt;Chroot provides the ability for a process to start with a different root directory to the parent OS. This allows different files to appear in the root.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cgroups (Control Groups)
&lt;/h2&gt;

&lt;p&gt;CGroups limit the amount of resources a process can consume. These cgroups are values defined in particular files within the /proc directory.&lt;/p&gt;

&lt;p&gt;To see the mappings, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/$DBPID/cgroup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd0norlt6vqkz8k25na61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd0norlt6vqkz8k25na61.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
These are mapped to other cgroup directories on disk at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls /sys/fs/cgroup/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuaq8kz7defmn9ndff69u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fuaq8kz7defmn9ndff69u.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
What are the CPU stats for a process?&lt;br&gt;
The CPU stats and usage is stored within a file too!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /sys/fs/cgroup/cpu,cpuacct/docker/$DBID/cpuacct.stat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CPU shares limit is also defined here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /sys/fs/cgroup/cpu,cpuacct/docker/$DBID/cpu.shares
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F38kic45hwlhxeg2niajd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F38kic45hwlhxeg2niajd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
All the Docker cgroups for the container's memory configuration are stored within:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls /sys/fs/cgroup/memory/docker/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fawlbddqq7rgfwil9g9sb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fawlbddqq7rgfwil9g9sb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Each of the directory is grouped based on the container ID assigned by Docker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DBID=$(docker ps --no-trunc | grep 'db' | awk '{print $1}')
WEBID=$(docker ps --no-trunc | grep 'nginx' | awk '{print $1}')
ls /sys/fs/cgroup/memory/docker/$DBID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffby0wk0ennp32lt5b028.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffby0wk0ennp32lt5b028.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
How to configure cgroups?&lt;br&gt;
One of the properties of Docker is the ability to control memory limits. This is done via a cgroup setting.&lt;/p&gt;

&lt;p&gt;By default, containers have no limit on the memory. We can view this via docker stats command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker stats db --no-stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb6f8cea7x5js1grhpf3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fb6f8cea7x5js1grhpf3t.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
The memory quotes are stored in a file called memory.limit_in_bytes.&lt;/p&gt;

&lt;p&gt;By writing to the file, we can change the limit limits of a process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 8000000 &amp;gt;/sys/fs/cgroup/memory/docker/$DBID/memory.limit_in_bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you read the file back, you'll notice it's been converted to 7999488.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /sys/fs/cgroup/memory/docker/$DBID/memory.limit_in_bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0s2ttm8ir7y7z8qw89ke.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0s2ttm8ir7y7z8qw89ke.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
When checking Docker Stats again, the memory limit of the process is now 7.629M -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker stats db --no-stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flpzesp472zb6aepwv50k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flpzesp472zb6aepwv50k.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Seccomp / AppArmor
&lt;/h2&gt;

&lt;p&gt;All actions with Linux is done via syscalls. The kernel has 330 system calls that perform operations such as read files, close handles and check access rights. All applications use a combination of these system calls to perform the required operations.&lt;/p&gt;

&lt;p&gt;AppArmor is a application defined profile that describes which parts of the system a process can access.&lt;/p&gt;

&lt;p&gt;It's possible to view the current AppArmor profile assigned to a process via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/$DBPID/attr/current
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fry7y0p4c8eu8nplok6i0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fry7y0p4c8eu8nplok6i0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
The default AppArmor profile for Docker is docker-default (enforce).&lt;/p&gt;

&lt;p&gt;Prior to Docker 1.13, it stored the AppArmor Profile in /etc/apparmor.d/docker-default (which was overwritten when Docker started, so users couldn't modify it. After v1.13, Docker now generates docker-default in tmpfs, uses apparmor_parser to load it into kernel, then deletes the file&lt;/p&gt;

&lt;p&gt;The template can be found at &lt;a href="https://github.com/moby/moby/blob/a575b0b1384b2ba89b79cbd7e770fbeb616758b3/profiles/apparmor/template.go" rel="noopener noreferrer"&gt;https://github.com/moby/moby/blob/a575b0b1384b2ba89b79cbd7e770fbeb616758b3/profiles/apparmor/template.go&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Seccomp provides the ability to limit which system calls can be made, blocking aspects such as installing Kernel Modules or changing the file permissions.&lt;/p&gt;

&lt;p&gt;The default allowed calls with Docker can be found at &lt;a href="https://github.com/moby/moby/blob/a575b0b1384b2ba89b79cbd7e770fbeb616758b3/profiles/seccomp/default.json" rel="noopener noreferrer"&gt;https://github.com/moby/moby/blob/a575b0b1384b2ba89b79cbd7e770fbeb616758b3/profiles/seccomp/default.json&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;When assigned to a process it means the process will be limited to a subset of the ability system calls. If it attempts to call a blocked system call is will recieve the error "Operation Not Allowed".&lt;/p&gt;

&lt;p&gt;The status of SecComp is also defined within a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/$DBPID/status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/$DBPID/status | grep Seccomp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl1gcabtdrokr8jiczykk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl1gcabtdrokr8jiczykk.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
The flag meaning are: 0: disabled 1: strict 2: filtering&lt;/p&gt;
&lt;h2&gt;
  
  
  Capabilities
&lt;/h2&gt;

&lt;p&gt;Capabilities are groupings about what a process or user has permission to do. These Capabilities might cover multiple system calls or actions, such as changing the system time or hostname.&lt;/p&gt;

&lt;p&gt;The status file also containers the Capabilities flag. A process can drop as many Capabilities as possible to ensure it's secure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/$DBPID/status | grep ^Cap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu41l69j1ojzqugwci3ir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu41l69j1ojzqugwci3ir.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
The flags are stored as a bitmask that can be decoded with capsh&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;capsh --decode=00000000a80425fb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq0s04ap11g8nkr229c7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq0s04ap11g8nkr229c7a.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope you found this article worth reading!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>linux</category>
      <category>container</category>
      <category>kubernetes</category>
    </item>
  </channel>
</rss>
