Logo

dev-resources.site

for different kinds of informations.

Refactoring 019 - Reify Email Addresses

Published at
12/5/2024
Categories
javascript
refactoring
designpatterns
beginners
Author
mcsee
Author
5 person written this
mcsee
open
Refactoring 019 - Reify Email Addresses

Sayit once and only once

TL;DR: Avoid duplicate email validations.

Problems Addressed

Related Code Smells

Steps

  1. Identify where email validation logic is duplicated.
  2. Create an Email Address class to encapsulate validation rules.
  3. Refactor code to use the Email Address class instead of raw strings.

Sample Code

Before

public class Person {
    private String emailAddress;
    // Primitive Obsession

    public void setEmailAddress(String emailAddress) {
        // Duplicated code
        if (!emailAddress.matches(
            "^[\\w.%+-]+@[\\w.-]+\\.[a-zA-Z]{2,}$")) {
            throw new IllegalArgumentException(
                "Invalid email address format");
        }
        this.emailAddress = emailAddress;
    }
}

public class JobApplication {
    private String applicantEmailAddress;

    public void setApplicantEmailAddress(String emailAddress) {
        // Duplicated code
        if (!emailAddress.matches(
            "^[\\w.%+-]+@[\\w.-]+\\.[a-zA-Z]{2,}$")) {
            throw new IllegalArgumentException(
                "Invalid email address format");
        }
        this.applicantEmailAddress = emailAddress;
    }
}
Enter fullscreen mode Exit fullscreen mode

After

public class EmailAddress {
    // 2. Create an `EmailAddress` class to encapsulate validation rules.
    private final String value;

    public EmailAddress(String value) {
        // The rules are in a single place
        // And all objects are created valid
        if (!value.matches("^[\\w.%+-]+@[\\w.-]+\\.[a-zA-Z]{2,}$")) {
            throw new IllegalArgumentException(
                "Invalid email address format");
        }
        this.value = value;
    }
}

public class Person {
    private final EmailAddress emailAddress;

    public Person(EmailAddress emailAddress) {
        // 1. Identify where email validation logic is duplicated.
        // 3. Refactor code to use the `Email Address`
        // class instead of raw strings.
        // No validation is required
        this.emailAddress = emailAddress;
    } 
}

public class JobApplication {
    private EmailAddress applicantEmailAddress;

    public JobApplication(EmailAddress applicantEmailAddress) {
        this.applicantEmailAddress = applicantEmailAddress;
    }
}
Enter fullscreen mode Exit fullscreen mode

Type

[X] Semi-Automatic

Safety

This refactoring is safe if you replace all occurrences of raw email strings with the 'EmailAddress' class and ensure all tests pass.

Why is the Code Better?

You make email validation consistent across your application.

Since validation rules are centralized in one place, the code becomes easier to maintain.

You also reduce the risk of bugs caused by inconsistent logic.

In the real world, Email Addresses are small objects that exist and are not strings.

The refactored code is closer to the real world MAPPER

Notice that bijection names are essential. It would help to create an 'EmailAddress', not an 'Email', since the Email should map to the actual message.

Don't let Premature Optimizators tell you this has a performance penalty.

They never do actual benchmarks with real world data.

Refactor with AI

Without Proper Instructions With Specific Instructions
ChatGPT ChatGPT
Claude Claude
Perplexity Perplexity
Copilot Copilot
Gemini Gemini

Tags

  • Encapsulation

Related Refactorings

Credits

Image by Gerd Altmann on Pixabay


This article is part of the Refactoring Series.

refactoring Article's
30 articles in total
Favicon
Python: Refactoring to Patterns
Favicon
STOP Writing Dirty Code: Fix The Data Class Code Smell Now!
Favicon
7 Ways to Refactor Your Flutter Application
Favicon
Những Tip đơn giản giúp đoạn code trở nên CLEAR và MAINTAIN dễ hơn
Favicon
Refactoring 021 - Remove Dead Code
Favicon
React v19, unboxing! 📦
Favicon
De software legacy a oportunitat estratègica: El punt de partida (I)
Favicon
The Backend Testing Breakup 💔
Favicon
Simplifying your code: replacing heavy packages with lightweight solutions
Favicon
The Rewrite Trap: A Programmer's Survival Guide
Favicon
Refactoring: The Art of Polishing Code
Favicon
El verdadero valor del software no siempre está en el presente
Favicon
Refactoring 019 - Reify Email Addresses
Favicon
How LLMs Revolutionize Coding Efficiency
Favicon
Effective Strategies for Refactoring a Large Codebase: Best Practices and Approaches
Favicon
Convert a ReactJS app from Vite to Nx
Favicon
Simplifying Conditional Expressions in C#: Tips for Clean and Readable Code
Favicon
Simplifying Method Calls in C#: Techniques for Cleaner and More Maintainable Code
Favicon
Mastering Clean Code: 4 Essential Techniques for Organizing Data in C#
Favicon
Refactoring: Moving Features Between Objects
Favicon
Composing Methods: A Practical Guide to Clean Code
Favicon
Refactoring 017 - Convert Attributes to Sets
Favicon
Como Refatorar Seu Código Com Muitos If-Else? Part 2
Favicon
Stop Re-Implementing Code: Use Extract Method in Rust
Favicon
De lo funcional hasta lo legible con Tidyings
Favicon
The Double-Edged Sword of IEnumerable and yield return in C#
Favicon
In Theory: Self-Correcting Software - Part 2
Favicon
Make your package.json readable again by humans: organizing npm scripts with shell files
Favicon
Transforming DevEx Through Bulk Refactoring (and How AI Can Assist)
Favicon
Refactoring for Efficiency: Tackling Performance Issues in Data-Heavy Pages

Featured ones: