Rule of Three

The Rule of Three is a pragmatic approach to the Don't Repeat Yourself (Core Principle). While DRY emphasizes reducing duplication to maintain cleaner and more maintainable code, the Rule of Three acknowledges that duplication is sometimes unavoidable or even beneficial in the short term.

Key Points

  1. Duplication Tolerance:

    • First Time: When you write a piece of code for the first time, it's natural and necessary. No duplication exists at this stage.
    • Second Time: When you need to duplicate code a second time, it's at times acceptable. This allows you to explore different contexts and understand how the code is being reused.
    • Third Time: When you find yourself duplicating code for the third time, it's a signal that the code should be refactored. By the third instance, it's clear that the functionality is common enough to warrant abstraction.
  2. Advantages:

    • Clarity: Initially, allowing some duplication can make the code clearer and simpler to understand, especially when the exact needs of abstraction are not yet evident.
    • Flexibility: By the time you need to abstract the duplicated code, you have better insights into how it should be structured to serve multiple use cases effectively.
    • Avoiding Premature Abstraction: Prematurely abstracting code can lead to over-engineering. The Rule of Three helps in avoiding unnecessary complexity.
  3. Application:

    • Monitor for duplication during code reviews.
    • Use the third occurrence as a trigger to refactor and abstract the common code.
    • Ensure that the abstraction is well-named and self-documenting to maintain code readability.

Example

// First time: Code to send an email
public void sendEmail(String recipient, String subject, String body) {
    // logic to send email
}

// Second time: Code to send an SMS
public void sendSms(String phoneNumber, String message) {
    // logic to send SMS
}

// Third time: Similar logic appears again for sending notifications
public void sendNotification(String type, String recipient, String message) {
    if (type.equals("email")) {
        sendEmail(recipient, "Notification", message);
    } else if (type.equals("sms")) {
        sendSms(recipient, message);
    }
}

// Refactor the common sending logic
public void send(String type, String recipient, String subject, String message) {
    if (type.equals("email")) {
        // logic to send email
    } else if (type.equals("sms")) {
        // logic to send SMS
    }
}

By following the Rule of Three, you ensure that your code remains maintainable, readable, and efficient. This approach strikes a balance between avoiding premature optimization and adhering to the DRY principle.


Backlinks