<?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: David Martinez</title>
    <description>The latest articles on DEV Community by David Martinez (@davidmrtz-dev).</description>
    <link>https://dev.to/davidmrtz-dev</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%2F252220%2F95c16c69-a2db-4760-a00d-74d0801075ea.jpg</url>
      <title>DEV Community: David Martinez</title>
      <link>https://dev.to/davidmrtz-dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davidmrtz-dev"/>
    <language>en</language>
    <item>
      <title>Mail Pilot ✈️ – Your Inbox, Now a Remote Control</title>
      <dc:creator>David Martinez</dc:creator>
      <pubDate>Sat, 07 Jun 2025 19:36:18 +0000</pubDate>
      <link>https://dev.to/davidmrtz-dev/mail-pilot-your-inbox-now-a-remote-control-3a6d</link>
      <guid>https://dev.to/davidmrtz-dev/mail-pilot-your-inbox-now-a-remote-control-3a6d</guid>
      <description>&lt;p&gt;This is a submission for the &lt;a href="https://dev.to/challenges/postmark"&gt;Postmark Challenge: Inbox Innovators&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Mail Pilot is a lightweight, email-driven control system for home automation. It turns any inbox into a secure command center capable of operating physical devices—from light switches to door locks—via simple email instructions.&lt;/p&gt;

&lt;p&gt;More than just a clever use of Postmark's inbound parsing, Mail Pilot explores a future where remote control can work reliably over the most ubiquitous and low-barrier protocol of all: email.&lt;/p&gt;

&lt;p&gt;The MVP connects an ESP8266 device to a Rails API that receives and processes email commands. But the concept scales: with authentication, scheduling, and multi-device orchestration, Mail Pilot could offer a resilient, accessible layer of automation on top of existing smart home systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;For judging purposes, the system is running locally with ngrok and a Wi-Fi-connected ESP8266. Commands like &lt;code&gt;ROOM_1_ON&lt;/code&gt; or &lt;code&gt;DOOR_OPEN&lt;/code&gt; can be sent via email, and the device will fetch and execute them.&lt;/p&gt;

&lt;p&gt;🖼️ System Diagram:&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.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%2Fk0788a2tpyqfranteee4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fk0788a2tpyqfranteee4.png" alt="Mail Pilot System Diagram" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📽️ Demo video: &lt;a href="https://youtube.com/shorts/1gQT24cXS6g?si=CpL7AsGcChsTbJuV" rel="noopener noreferrer"&gt;Watch on YouTube Shorts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⛓️ Test it (on request): I’ll gladly expose the instance via ngrok for live review. DM me if you'd like to try it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Repository
&lt;/h2&gt;

&lt;p&gt;🔗 Backend (Rails API): &lt;a href="https://github.com/davidmrtz-dev/mail_pilot" rel="noopener noreferrer"&gt;github.com/davidmrtz-dev/mail_pilot&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🔗 Firmware (ESP8266): &lt;a href="https://github.com/davidmrtz-dev/mail_pilot_micro" rel="noopener noreferrer"&gt;github.com/davidmrtz-dev/mail_pilot_firmware&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Ruby on Rails 7 with a RESTful interface and Postmark's inbound webhook to receive emails as commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device&lt;/strong&gt;: NodeMCU ESP8266 polling the API and executing commands using relays, servos, and OLED display feedback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infra&lt;/strong&gt;: Dockerized PostgreSQL + Rails stack for portability. Ngrok is used to tunnel the local API during testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Postmark’s reliability and ease of use made it ideal for converting emails into executable actions in real-time.&lt;/p&gt;




&lt;p&gt;Thanks for reading, and thank you Postmark for the opportunity to build something unexpected, fun, and potentially useful.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>postmarkchallenge</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>🔒 Exploring the Singleton Design Pattern in Ruby</title>
      <dc:creator>David Martinez</dc:creator>
      <pubDate>Wed, 06 Nov 2024 16:35:15 +0000</pubDate>
      <link>https://dev.to/davidmrtz-dev/exploring-the-singleton-design-pattern-in-ruby-42o2</link>
      <guid>https://dev.to/davidmrtz-dev/exploring-the-singleton-design-pattern-in-ruby-42o2</guid>
      <description>&lt;p&gt;Welcome! Today, let’s dive into the Singleton design pattern, a fundamental yet powerful pattern in object-oriented programming.&lt;br&gt;
We’ll explore its structure, benefits, and practical use cases in Ruby.&lt;/p&gt;
&lt;h2&gt;
  
  
  Introducing the Singleton Pattern 🧩
&lt;/h2&gt;

&lt;p&gt;The Singleton is a creational design pattern that ensures a class has only one instance and provides a global point of access to it.&lt;/p&gt;

&lt;p&gt;This pattern is ideal for managing resources like database connections or configuration settings where only one instance is necessary.&lt;/p&gt;
&lt;h2&gt;
  
  
  When to Use the Flyweight Pattern?
&lt;/h2&gt;

&lt;p&gt;🔸 Use Singleton when you need to control access to shared resources or ensure that only one instance of a class is used throughout the application.&lt;/p&gt;

&lt;p&gt;🔸 This pattern is helpful for scenarios requiring centralized management, such as logging, caching, or connection pooling.&lt;/p&gt;
&lt;h3&gt;
  
  
  Problem Scenario
&lt;/h3&gt;

&lt;p&gt;Imagine an application where multiple parts of the code access configuration settings.&lt;br&gt;
Without a Singleton, you risk multiple, inconsistent instances of these settings, leading to bugs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;The Singleton pattern ensures only one instance of the configuration class exists.&lt;br&gt;
Any part of the application can access this instance without worrying about duplicates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fzbhrhdhmnkfilor6srns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzbhrhdhmnkfilor6srns.png" alt="singleton-uml-diagram" width="365" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, the Singleton pattern is applied to manage application configuration.&lt;/p&gt;

&lt;p&gt;🔹 The Singleton class controls access to the single instance.&lt;/p&gt;

&lt;p&gt;🔹 The&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 method provides a global point of access, ensuring only one instance exists.

## How does it Work?
1️⃣ Define a

 ```self.instance```

 method to return the single instance of the class.

2️⃣ Use

 ```@instance ||= new```

 inside the method to create the instance if it doesn’t already exist.

3️⃣ Privateize

 ```new```

 to prevent external code from creating additional instances.

💡 Note: The Singleton pattern restricts object creation, ensuring only one instance exists.

## Why Use the Singleton Pattern?
🔒 Simplifies access to shared resources.

🔒 Reduces the risk of inconsistent states across the application.

🔒 Provides centralized control and management of instances.

🔒 Optimizes memory usage by limiting unnecessary instance creation.

## Show me the code


```python
# Singleton class for AppConfig
class AppConfig
  @instance = nil

  # Ensures only one instance of AppConfig exists
  def self.instance
    @instance ||= new
  end

  # Stores application configurations
  attr_accessor :settings

  # Sample initialization of settings
  def initialize
    @settings = { app_name: "MyApp", version: "1.0.0" }
  end

  # Prevents external instantiation
  private_class_method :new
end

# Client code
def main
  config1 = AppConfig.instance
  config2 = AppConfig.instance

  puts config1.settings  # =&amp;gt; {:app_name=&amp;gt;"MyApp", :version=&amp;gt;"1.0.0"}
  config2.settings[:version] = "2.0.0"

  puts config1.settings  # =&amp;gt; {:app_name=&amp;gt;"MyApp", :version=&amp;gt;"2.0.0"}
  puts config1.equal?(config2)  # =&amp;gt; true
end

main

# Output
# {:app_name=&amp;gt;"MyApp", :version=&amp;gt;"1.0.0"}
# {:app_name=&amp;gt;"MyApp", :version=&amp;gt;"2.0.0"}
# true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The Singleton pattern is a powerful tool to control resource usage by ensuring a class has only one instance.&lt;/p&gt;

&lt;p&gt;🔺 It’s ideal for scenarios where centralized control is needed, like managing configurations.&lt;/p&gt;

&lt;p&gt;🔺 The Singleton pattern simplifies code, minimizes memory footprint, and ensures consistency.&lt;/p&gt;

&lt;p&gt;🔺 By implementing Singleton, you create a reliable way to manage shared resources across the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Quest!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com.br/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612" rel="noopener noreferrer"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com.br/Head-First-Design-Patterns-Brain-Friendly/dp/0596007124" rel="noopener noreferrer"&gt;Head First Design Patterns: A Brain-Friendly Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/davidmrtz-dev/ruby-d-patterns/blob/master/creational/singleton/bin/main.rb" rel="noopener noreferrer"&gt;Code example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💻 You can find this and other design patterns &lt;a href="https://github.com/davidmrtz-dev/ruby-d-patterns" rel="noopener noreferrer"&gt;here&lt;/a&gt; 📚&lt;/p&gt;

</description>
      <category>codingstandards</category>
      <category>ruby</category>
      <category>softwaredevelopment</category>
      <category>engineering</category>
    </item>
    <item>
      <title>Coding Standards in the Software Industry: A Focus on Ruby</title>
      <dc:creator>David Martinez</dc:creator>
      <pubDate>Sat, 15 Jun 2024 23:46:16 +0000</pubDate>
      <link>https://dev.to/davidmrtz-dev/coding-standards-in-the-software-industry-a-focus-on-ruby-n6a</link>
      <guid>https://dev.to/davidmrtz-dev/coding-standards-in-the-software-industry-a-focus-on-ruby-n6a</guid>
      <description>&lt;h2&gt;
  
  
  Introduction to Coding Standards 📚
&lt;/h2&gt;

&lt;p&gt;In the dynamic and ever-evolving realm of software development, coding standards stand as a cornerstone, guiding developers towards crafting maintainable, readable, and robust codebases.&lt;br&gt;
These established guidelines dictate the structure, formatting, and overall style of code, ensuring consistency and facilitating seamless collaboration among developers.&lt;br&gt;
Embracing coding standards not only elevates the quality of the code but also streamlines the development process, fostering a culture of shared understanding and minimizing the potential for errors.&lt;/p&gt;

&lt;p&gt;This post delves into the profound significance of coding standards in the software industry, with a particular focus on their application in Ruby development.&lt;br&gt;
By examining the rationale behind these standards, exploring prevalent conventions, and showcasing practical examples, we aim to illuminate their crucial role in fostering high-quality software development.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Compelling Case for Coding Standards 🔎
&lt;/h2&gt;

&lt;p&gt;Coding standards transcend mere aesthetics, offering a multitude of benefits that permeate the very fabric of software development.&lt;br&gt;
Their implementation fosters a cohesive and consistent codebase, enhancing its readability and maintainability.&lt;br&gt;
As developers navigate through the code, they are presented with a familiar and structured environment, reducing the cognitive burden associated with deciphering unfamiliar coding styles.&lt;br&gt;
This, in turn, expedites the debugging and troubleshooting process, enabling developers to swiftly identify and rectify issues.&lt;/p&gt;

&lt;p&gt;Furthermore, coding standards promote collaboration and teamwork within development teams.&lt;br&gt;
By establishing a common language and set of guidelines, developers can seamlessly integrate their contributions, ensuring that the codebase remains cohesive and well-organized.&lt;br&gt;
This collaborative approach fosters knowledge sharing and reduces the risk of introducing inconsistencies or conflicts.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Role of Coding Standards in Ruby Development 💎
&lt;/h2&gt;

&lt;p&gt;The Ruby programming language, renowned for its elegance and expressiveness, also adheres to a set of well-defined coding standards.&lt;br&gt;
These guidelines, meticulously crafted by the Ruby community, aim to promote consistency, readability, and maintainability across Ruby codebases.&lt;/p&gt;

&lt;p&gt;One of the fundamental tenets of Ruby coding standards is the emphasis on indentation.&lt;br&gt;
Ruby utilizes spaces for indentation, typically two spaces per level, to visually delineate code blocks and enhance its readability.&lt;br&gt;
This consistent indentation scheme fosters a clear understanding of the code's structure and flow, enabling developers to quickly grasp the relationships between different code segments.&lt;/p&gt;
&lt;h2&gt;
  
  
  Beyond Aesthetics: The Far-Reaching Benefits of Coding Standards ✨
&lt;/h2&gt;

&lt;p&gt;🔮 &lt;strong&gt;More consistent&lt;/strong&gt;: Uniform coding practices ensure a consistent codebase, which is vital when multiple developers work on the same project.&lt;/p&gt;

&lt;p&gt;🔮 &lt;strong&gt;More Readable&lt;/strong&gt;: Consistent indentation, meaningful naming conventions, and well-structured code blocks make it easier for developers to understand and navigate the codebase,&lt;br&gt;
saving time and effort during code reviews and maintenance tasks.&lt;/p&gt;

&lt;p&gt;🔮 &lt;strong&gt;More Maintainable&lt;/strong&gt;: Well-formatted code is easier to modify and extend, reducing the likelihood of introducing errors and facilitating future enhancements.&lt;br&gt;
This maintainability not only saves time but also ensures the codebase remains adaptable to evolving requirements.&lt;/p&gt;

&lt;p&gt;🔮 &lt;strong&gt;Less Prone to Errors&lt;/strong&gt;: Consistent coding conventions minimize the potential for syntax errors and logical mistakes, leading to cleaner, more reliable code.&lt;br&gt;
This reduction in errors translates to fewer bugs, improved application stability, and a more positive user experience.&lt;/p&gt;

&lt;p&gt;🔮 &lt;strong&gt;Enhanced Collaboration&lt;/strong&gt;: Shared coding standards foster a common language among developers, enabling seamless collaboration and knowledge sharing.&lt;br&gt;
This collaborative approach streamlines the development process, reduces conflicts, and promotes a sense of ownership among team members.&lt;/p&gt;

&lt;p&gt;🔮 &lt;strong&gt;More efficient&lt;/strong&gt;: Adhering to standards can streamline the development process, as developers spend less time understanding code written by others.&lt;/p&gt;
&lt;h2&gt;
  
  
  Practical Applications of Coding Standards in Ruby ⚙️
&lt;/h2&gt;

&lt;p&gt;Ruby is renowned for its elegant syntax and readability. Adhering to coding standards enhances these attributes. Below are some widely accepted Ruby coding standards:&lt;/p&gt;
&lt;h3&gt;
  
  
  Naming Conventions - Classes and Modules
&lt;/h3&gt;

&lt;p&gt;Class and module names should be written in CamelCase, starting with an uppercase letter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;MyModule&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Naming Conventions - Methods and Variables
&lt;/h3&gt;

&lt;p&gt;Method and variable names should be written in snake_case, all in lowercase with words separated by underscores.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;my_variable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Indentation
&lt;/h3&gt;

&lt;p&gt;Use two spaces per indentation level. Avoid using tabs as they can be rendered differently in various editors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;some_condition&lt;/span&gt;
    &lt;span class="n"&gt;do_something&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;do_something_else&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Line Length
&lt;/h3&gt;

&lt;p&gt;Keep lines to a maximum of 80 characters. This promotes readability and helps prevent horizontal scrolling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Good
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Bad
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_long_method_with_a_descriptive_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arg8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# Method body here
&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Method Definitions
&lt;/h3&gt;

&lt;p&gt;Avoid defining methods with more than one or two parameters. If a method requires multiple parameters, consider using a hash to pass them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Good
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
  &lt;span class="c1"&gt;# method implementation
&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Bad
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# method implementation
&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  String Literals
&lt;/h3&gt;

&lt;p&gt;Use single quotes for string literals unless you need string interpolation or special symbols.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Good
&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# Bad
&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Interpolation
&lt;/span&gt;&lt;span class="n"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, #{name}!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Blocks and Lambdas
&lt;/h3&gt;

&lt;p&gt;Prefer the &lt;code&gt;do...end&lt;/code&gt; syntax for multiline blocks and &lt;code&gt;{}&lt;/code&gt; for single-line blocks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Multiline block
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="n"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Single-line block
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use lambda for anonymous functions and -&amp;gt; for concise syntax.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Good
&lt;/span&gt;&lt;span class="n"&gt;my_lambda&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Bad
&lt;/span&gt;&lt;span class="n"&gt;my_lambda&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Comments and Documentation
&lt;/h3&gt;

&lt;p&gt;Use comments judiciously to explain the why behind the code, not the what. Ensure that comments are up-to-date and reflect the current state of the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Good
# This method calculates the area of a rectangle
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Bad
# Calculate the area
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use RDoc or other documentation tools to generate detailed documentation for your classes and methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Good
# Calculates the area of a rectangle.
#
# @param length [Integer] The length of the rectangle.
# @param width [Integer] The width of the rectangle.
# @return [Integer] The area of the rectangle.
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Error Handling
&lt;/h3&gt;

&lt;p&gt;Handle errors gracefully using exceptions. Ensure that errors are logged appropriately and provide meaningful messages to the users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Good
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Division by zero error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="n"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Bad
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Coding standards serve as an invaluable tool in the software development arsenal, particularly in the realm of Ruby programming.&lt;br&gt;
By adhering to established guidelines, developers can craft code that is not only functional but also maintainable, readable, and collaborative.&lt;br&gt;
The benefits of coding standards extend far beyond aesthetics, encompassing enhanced code quality, reduced development time, and improved team productivity.&lt;br&gt;
As the software industry continues to evolve, embracing coding standards will remain paramount in fostering the creation of robust, scalable, and enduring software solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways 💡
&lt;/h2&gt;

&lt;p&gt;🔺 &lt;strong&gt;Consistent coding standards&lt;/strong&gt; enhance code quality, readability, and maintainability.&lt;/p&gt;

&lt;p&gt;🔺 &lt;strong&gt;Ruby coding standards&lt;/strong&gt; emphasize indentation, naming conventions, and readability.&lt;/p&gt;

&lt;p&gt;🔺 &lt;strong&gt;Adhering to coding standards&lt;/strong&gt; fosters collaboration, reduces errors, and streamlines development.&lt;/p&gt;

&lt;p&gt;🔺 &lt;strong&gt;Practical applications&lt;/strong&gt; of coding standards in Ruby include naming conventions, indentation, line length, and error handling.&lt;/p&gt;

&lt;p&gt;By embracing coding standards as a guiding principle in software development, developers can navigate the complexities of code with clarity, confidence, and cohesion,&lt;br&gt;
ultimately paving the way for the creation of exceptional software solutions.&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Keep coding, keep creating, and keep innovating!&lt;/strong&gt; 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://rubystyle.guide/"&gt;Ruby Style Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ruby-lang.org/en/community/ruby-coding-style-guide/"&gt;Ruby Coding Standards&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com.br/Art-Readable-Code-Practical-Techniques/dp/0596802293"&gt;The Art of Readable Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com.br/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rubocop.org/"&gt;RuboCop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>codingstandards</category>
      <category>ruby</category>
      <category>softwaredevelopment</category>
      <category>engineering</category>
    </item>
    <item>
      <title>🎨 Exploring the Abstract Factory Design Pattern in Ruby</title>
      <dc:creator>David Martinez</dc:creator>
      <pubDate>Thu, 09 May 2024 04:31:49 +0000</pubDate>
      <link>https://dev.to/davidmrtz-dev/exploring-the-abstract-factory-design-pattern-in-ruby-3206</link>
      <guid>https://dev.to/davidmrtz-dev/exploring-the-abstract-factory-design-pattern-in-ruby-3206</guid>
      <description>&lt;p&gt;Welcome! Today, let's embark on a journey into the Abstract Factory design pattern.&lt;br&gt;
We'll dive deep into its workings, explore real-world scenarios, and unveil its magic!&lt;/p&gt;

&lt;h2&gt;
  
  
  Unveiling the Abstract Factory Pattern ✨
&lt;/h2&gt;

&lt;p&gt;The Abstract Factory is a creational design pattern that furnishes an interface for creating families of related or dependent objects without specifying their concrete classes.&lt;/p&gt;

&lt;p&gt;This pattern revolves around a super-factory, known as an Abstract Factory, which generates other factories. These factories, in turn, produce objects related to specific families.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use the Abstract Factory Pattern?
&lt;/h2&gt;

&lt;p&gt;🔸 Use this pattern when your code needs to interact with various families of related products, yet you prefer not to bind it to the concrete classes of those products.&lt;/p&gt;

&lt;p&gt;🔸 It's beneficial when providing a library of classes for users to extend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem Scenario
&lt;/h3&gt;

&lt;p&gt;Consider developing a native application intended for multiple operating systems like Windows, Mac, and Linux.&lt;br&gt;
This application incorporates various UI elements such as buttons, inputs, text areas, and dialogs.&lt;/p&gt;

&lt;p&gt;Rendering these UI elements in accordance with each operating system's style poses a challenge.&lt;br&gt;
Additionally, avoiding code alterations whenever a new OS is supported is crucial.&lt;/p&gt;

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

&lt;p&gt;The Abstract Factory pattern suggests creating separate factory interfaces for each UI element type, like buttons, inputs, text areas, etc.&lt;br&gt;
Each factory interface defines methods to create these UI elements, returning abstract products such as Button, Input, Textarea, etc.&lt;/p&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%2Fi.ibb.co%2FPh9NX8R%2FAbstract-Factory-Abstract-Factory.jpg" 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%2Fi.ibb.co%2FPh9NX8R%2FAbstract-Factory-Abstract-Factory.jpg" alt="abstract-factory-uml-diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Further, interfaces are declared for each distinct product of the UI elements, such as Button, Input, Textarea, etc., with common methods.&lt;/p&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%2Fi.ibb.co%2F19gJ4y1%2FAbstract-Factory-Factory-Button.jpg" 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%2Fi.ibb.co%2F19gJ4y1%2FAbstract-Factory-Factory-Button.jpg" alt="button-class-uml-diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concrete factories implement these interfaces and produce concrete products like WindowsButton, WindowsInput, WindowsTextarea, MacButton, MacInput, MacTextarea, etc.&lt;/p&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%2Fi.ibb.co%2FkgyHkxj%2FAbstract-Factory-Factory-Dialog.jpg" 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%2Fi.ibb.co%2FkgyHkxj%2FAbstract-Factory-Factory-Dialog.jpg" alt="dialog-class-uml-diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, the Abstract Factory pattern is utilized to create UI elements for Windows and Mac operating systems.&lt;/p&gt;

&lt;p&gt;🔹 The Abstract Factory interface declares factory methods to create UI elements like createButton, createInput, createTextarea, etc.&lt;/p&gt;

&lt;p&gt;🔹 Concrete factories implement these factory methods to create OS-specific UI elements.&lt;/p&gt;

&lt;p&gt;🔹 Concrete products implement UI element interfaces like Button, Input, Textarea, etc.&lt;/p&gt;

&lt;p&gt;🔹 Client code utilizes the Abstract Factory interface to create UI elements without knowledge of their concrete classes.&lt;/p&gt;

&lt;p&gt;🔹 All UI elements are treated uniformly by client code, regardless of their concrete class.&lt;/p&gt;

&lt;p&gt;🔹 Client code is aware of the render method in all UI elements but doesn't concern itself with how it's implemented in each concrete class.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does it Work?
&lt;/h2&gt;

&lt;p&gt;1️⃣ Concrete products implement UI element interfaces like Button, Input, Textarea, etc.&lt;/p&gt;

&lt;p&gt;2️⃣ Concrete factories implement the Abstract Factory interface, producing concrete products tailored to specific OSes.&lt;/p&gt;

&lt;p&gt;3️⃣ The Abstract Factory interface declares factory methods for creating UI elements like createButton, createInput, createTextarea, etc.&lt;/p&gt;

&lt;p&gt;4️⃣ Abstract factories spawn concrete factories that adhere to the Abstract Factory interface.&lt;/p&gt;

&lt;p&gt;💡 Note: The abstract factory can optimize by reusing existing objects rather than creating new ones every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Embrace the Abstract Factory?
&lt;/h2&gt;

&lt;p&gt;🔮 Ensures compatibility among products obtained from a factory.&lt;/p&gt;

&lt;p&gt;🔮 Avoids tight coupling between concrete products and client code.&lt;/p&gt;

&lt;p&gt;🔮 Facilitates seamless replacement of the entire product family by switching concrete factories.&lt;/p&gt;

&lt;p&gt;🔮 Enables introducing new product variants without disrupting existing client code.&lt;/p&gt;

&lt;p&gt;🔮 Aligns with the Open/Closed Principle by extending the codebase with new classes instead of modifying existing ones.&lt;/p&gt;

&lt;p&gt;🔮 Adheres to the Single Responsibility Principle by consolidating product creation in one place, enhancing code maintainability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GUIFactory "Interface"
# (since interfaces do not exist in Ruby, we will use a module to define the interface)
&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;GUIFactory&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_button&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_checkbox&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WinFactory&lt;/span&gt;
  &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;GUIFactory&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_button&lt;/span&gt;
    &lt;span class="n"&gt;WindowsButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_checkbox&lt;/span&gt;
    &lt;span class="n"&gt;WindowsCheckbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MacFactory&lt;/span&gt;
  &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;GUIFactory&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_button&lt;/span&gt;
    &lt;span class="n"&gt;MacButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_checkbox&lt;/span&gt;
    &lt;span class="n"&gt;MacCheckbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;# Checkbox
&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;Checkbox&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_change&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MacCheckbox&lt;/span&gt;
  &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;Checkbox&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MacCheckbox render&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_change&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MacCheckbox on_change&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WindowsCheckbox&lt;/span&gt;
  &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;Checkbox&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WindowsCheckbox render&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_change&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WindowsCheckbox on_change&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Button
&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_click&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MacButton&lt;/span&gt;
  &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MacButton render&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_click&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MacButton on_click&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WindowsButton&lt;/span&gt;
  &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WindowsButton render&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_click&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WindowsButton on_click&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Application
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_ui&lt;/span&gt;
    &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@factory.create_button&lt;/span&gt;
    &lt;span class="n"&gt;checkbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@factory.create_checkbox&lt;/span&gt;
    &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;
    &lt;span class="n"&gt;checkbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Client
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
  &lt;span class="n"&gt;op_system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mac&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;op_system&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;win&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WinFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MacFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_ui&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Output
&lt;/span&gt;&lt;span class="n"&gt;MacButton&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;
&lt;span class="n"&gt;MacCheckbox&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The Abstract Factory pattern furnishes an interface for creating families of related or dependent objects without specifying their concrete classes.&lt;/p&gt;

&lt;p&gt;🔺 This pattern is advantageous when your code interacts with various families of related products without relying on their concrete classes.&lt;/p&gt;

&lt;p&gt;🔺 It's beneficial when providing a library of classes for users to extend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Quest!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com.br/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612" rel="noopener noreferrer"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://refactoring.guru/design-patterns/abstract-factory" rel="noopener noreferrer"&gt;Abstract Factory Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/davidmrtz-dev/ruby-d-patterns/blob/master/creational/abstract_factory/bin/main.rb" rel="noopener noreferrer"&gt;Code example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💻 You can find this and other design patterns &lt;a href="https://github.com/davidmrtz-dev/ruby-d-patterns" rel="noopener noreferrer"&gt;here&lt;/a&gt; 📚&lt;/p&gt;

</description>
      <category>abstractfactoryexplained</category>
      <category>designpatterninsights</category>
      <category>codingtips</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Factory Method Pattern in Ruby</title>
      <dc:creator>David Martinez</dc:creator>
      <pubDate>Wed, 17 Apr 2024 18:28:50 +0000</pubDate>
      <link>https://dev.to/davidmrtz-dev/factory-method-pattern-in-ruby-b0c</link>
      <guid>https://dev.to/davidmrtz-dev/factory-method-pattern-in-ruby-b0c</guid>
      <description>&lt;p&gt;This is the first post in the series on design patterns in Ruby.&lt;br&gt;
This series will cover different design patterns, including creational, structural, behavioral, and others.&lt;/p&gt;

&lt;p&gt;In this post, we will address the Factory Method design pattern. We will see how it works, use cases, advantages and disadvantages,&lt;br&gt;
as well as tips on cases where it is useful to implement this pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  What?
&lt;/h2&gt;

&lt;p&gt;The Factory Method is a creational design pattern that provides an interface for creating objects in a superclass,&lt;br&gt;
but allows subclasses to alter the type of objects that will be created.&lt;/p&gt;

&lt;p&gt;This pattern defines a method that should be used for creating objects instead of a direct call to the constructor.&lt;br&gt;
Subclasses can override this method to change the classes of objects that will be created.&lt;/p&gt;

&lt;h2&gt;
  
  
  When?
&lt;/h2&gt;

&lt;p&gt;🔸 This pattern is useful when a class cannot anticipate the class of objects it should create.&lt;/p&gt;

&lt;p&gt;🔸 This pattern is useful when a class wants its subclasses to specify the objects it will create.&lt;/p&gt;

&lt;p&gt;🔸 This pattern is useful when you want to provide a library of classes so that users can extend it.&lt;/p&gt;

&lt;p&gt;🔸 This pattern is useful if you want to save resources and improve performance by reusing existing objects instead of creating new ones.&lt;/p&gt;

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

&lt;p&gt;Imagine you are working on a Windows application that deploys multiple UI elements such as buttons, inputs, textareas, etc.&lt;br&gt;
In the first version of the application, you create a class for each UI element, so the Dialog class stores the code to create,&lt;br&gt;
manipulate, and display a dialog on the Windows OS. Your app gains popularity, so after some time, you are asked to add support for other operating systems.&lt;/p&gt;

&lt;p&gt;Since much of the Dialog logic is based on Windows, you need to create a new class for each operating system your app supports.&lt;br&gt;
Worse, if support for another operating system is requested in the future, you will have to create a new class to support the new operating system.&lt;/p&gt;

&lt;p&gt;As a result, your code becomes difficult to maintain, as each class has similar logic but with small differences.&lt;br&gt;
Additionally, every time support for a new operating system is requested, a new class must be created to support the new operating system.&lt;/p&gt;

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

&lt;p&gt;The Factory Method pattern solves the previous problem by defining a method that should be used for creating objects instead of a direct call to the constructor.&lt;br&gt;
Subclasses can override this method to change the classes of objects that will be created.&lt;/p&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%2Fi.ibb.co%2F9TNKd8q%2Fdialog-factory-method-1.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%2Fi.ibb.co%2F9TNKd8q%2Fdialog-factory-method-1.png" alt="dialog-diagram-factory-method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now it is possible to override the &lt;code&gt;create_button&lt;/code&gt; method in the Dialog subclasses to create a specific button for each operating system.&lt;br&gt;
However, the subclasses of the products can return different types of objects, which is why the factory method of the product base must return&lt;br&gt;
a defined type as an interface.&lt;/p&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%2Fi.ibb.co%2FR3h7N5g%2Fbutton-factory-method.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%2Fi.ibb.co%2FR3h7N5g%2Fbutton-factory-method.png" alt="dialog-diagram-factory-method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, both WindowsButton and MacButton implement the Button interface, which declares a &lt;code&gt;render&lt;/code&gt; method that will be implemented by the subclasses.&lt;br&gt;
Each button class implements the &lt;code&gt;render&lt;/code&gt; method differently, so that the Windows button renders a button with a Windows style, and the Mac button renders a&lt;br&gt;
button with a Mac style.&lt;/p&gt;

&lt;p&gt;🔹 The factory method in WindowsDialog returns WindowsButton objects, while the factory method in MacDialog returns MacButton objects.&lt;/p&gt;

&lt;p&gt;🔹 The client code does not see a difference between WindowsButton and MacButton objects, since both implement the same interface.&lt;/p&gt;

&lt;p&gt;🔹 The client treats all buttons in the same way, regardless of their concrete class.&lt;/p&gt;

&lt;p&gt;🔹 The client knows that all buttons have a &lt;code&gt;render&lt;/code&gt; method, but it does not know how this method is implemented in each concrete class.&lt;/p&gt;

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

&lt;p&gt;1️⃣ A common interface is declared for all products that will be produced by the creator and its subclasses.&lt;/p&gt;

&lt;p&gt;2️⃣ The concrete products are different implementations of the common interface.&lt;/p&gt;

&lt;p&gt;3️⃣ The creator declares a factory method that returns an object of the concrete products. It is important that the return type is the common interface.&lt;/p&gt;

&lt;p&gt;4️⃣ The subclasses of the creator override the factory method to return different types of products.&lt;/p&gt;

&lt;p&gt;💡 Note: The factory method should not create new objects all the time. Instead, the factory method should return existing objects stored in a cache or other source.&lt;/p&gt;

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

&lt;p&gt;📍 The Factory Method pattern follows the Open/Closed principle, which states that classes should be open for extension but closed for modification.&lt;/p&gt;

&lt;p&gt;📍 The Factory Method pattern allows subclasses to extend the logic of object creation without modifying the superclass code.&lt;/p&gt;

&lt;p&gt;📍 The Factory Method pattern follows the Single Responsibility Principle, which states that a class should do only one thing and do it well.&lt;/p&gt;

&lt;p&gt;📍 The Factory Method pattern allows subclasses to change the type of objects that will be created without modifying the superclass code.&lt;/p&gt;

&lt;p&gt;📍 The Factory Method pattern allows subclasses to reuse the superclass code to create objects of different types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Button "Interface"
# (since interfaces does not exist in Ruby, we will use a module to define the interface)
&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_click&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MacButton&lt;/span&gt;
  &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MacButton render&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_click&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MacButton on_click&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WindowsButton&lt;/span&gt;
  &lt;span class="n"&gt;include&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WindowsButton render&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_click&lt;/span&gt;
    &lt;span class="n"&gt;puts&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;WindowsButton on_click&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;# Dialog
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dialog&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="nd"&gt;@button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;create_button&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;
    &lt;span class="nd"&gt;@button.render&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_click&lt;/span&gt;
    &lt;span class="nd"&gt;@button.on_click&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_button&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#{self.class} has not implemented method &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#{__method__}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WindowsDialog&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;Dialog&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_button&lt;/span&gt;
    &lt;span class="n"&gt;WindowsButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MacDialog&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;Dialog&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_button&lt;/span&gt;
    &lt;span class="n"&gt;MacButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;end&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Client
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;
  &lt;span class="n"&gt;dialog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WindowsDialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;
  &lt;span class="n"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_click&lt;/span&gt;

  &lt;span class="n"&gt;dialog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MacDialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;
  &lt;span class="n"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;
  &lt;span class="n"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_click&lt;/span&gt;
&lt;span class="n"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Output
&lt;/span&gt;&lt;span class="n"&gt;WindowsButton&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;
&lt;span class="n"&gt;WindowsButton&lt;/span&gt; &lt;span class="n"&gt;on_click&lt;/span&gt;
&lt;span class="n"&gt;MacButton&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;
&lt;span class="n"&gt;MacButton&lt;/span&gt; &lt;span class="n"&gt;on_click&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The Factory Method is a creational design pattern that provides an interface for creating objects in a superclass,&lt;br&gt;
but allows subclasses to alter the type of objects that will be created.&lt;/p&gt;

&lt;p&gt;🔺 This pattern is useful when a class cannot anticipate the class of objects it should create.&lt;/p&gt;

&lt;p&gt;🔺 This pattern is useful when a class wants its subclasses to specify the objects it will create.&lt;/p&gt;

&lt;p&gt;🔺 This pattern is useful when you want to provide a library of classes so that users can extend it.&lt;/p&gt;

&lt;p&gt;🔺 This pattern is useful if you want to save resources and improve performance by reusing existing objects instead of creating new ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com.br/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612" rel="noopener noreferrer"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://refactoring.guru/design-patterns/factory-method" rel="noopener noreferrer"&gt;Factory Method Pattern&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/davidmrtz-dev/ruby-d-patterns/blob/master/creational/factory_method/bin/main.rb" rel="noopener noreferrer"&gt;Code example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💻 You can find this and other design patterns &lt;a href="https://github.com/davidmrtz-dev/ruby-d-patterns" rel="noopener noreferrer"&gt;here&lt;/a&gt; 📚&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
