Clean code
  • Overview
    • Introduction
    • Why is clean code so important?
    • What Is Clean Code?
    • How to write clean code?
    • Conventions
  • The key principles of clean code
    • Meaningful Names
    • Functions
    • Classes
    • Comments
    • Error Handling
      • Exception handling best practices
    • Unit Tests
    • Formatting
    • Objects and Data Structures
    • Simple Design Rules
    • Concurrency
    • Code Smells
  • Building Maintainable Software
    • Write Short Units of Code
    • Write Simple Units of Code
    • Write Code Once
    • Keep Unit Interfaces Small
    • Write Clean Code
    • Automate Tests
  • Bonus
    • SOLID Principle
      • SRP - Single Responsibility Principle
      • OCP - Open-Closed Principle
      • LSP - Liskov Substitution Principle
      • ISP - Interface Segregation Principle
      • DIP - Dependency Inversion Principle
    • LoD Principle
    • YAGNI Principle
    • DRY Principle
    • Fail Fast principle
    • Hollywood Principle
    • Library vs Framework
    • Coupling and Cohesion
    • AOP - Aspect-Oriented Programming
      • Building an AOP framework
    • OOP Design Pattern
    • Technical Dept
    • How to learn software Design and Architecture - Roadmap
    • Microservcies
      • Defining the scope of a microservice
      • Step-by-Step: How to Identify Over-Scoped Microservices
      • Benefits of Grouping or Consolidating Microservices
      • A practical step-by-step plan to consolidate microservice
Powered by GitBook
On this page
  • Example of "exactly the same"
  • Example of "similar to"
  • Example of "duplication of implementation"
  1. Bonus

DRY Principle

Don't Repeat Yourself Principle

DRY stand for "Don't Repeat Yourself," a basic principle of software development aimed at reducing the repetition of information. The DRY principle is stated as, "Every piece of knowledge or logic must have a single, unambiguous representation within a system."

Structured programming, Aspect Oriented Programming, Component Oriented Programming, and Design Patterns are all, in part, strategies for eliminating duplication.

Duplication manifests itself in many forms:

  • Lines of code that look exactly the same.

  • Lines of code that are similar to.

  • Duplication of implementation.

Example of "exactly the same"

class UserService {
    public void createUser(String email, String password) {
        if (isEmailValid(email)) {
            // create user
        }
    }
    
    private boolean isEmailValid(String email) {
        String pattern = "email pattern";
        Pattern pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(email);
        return matcher.matches();
    }
}

class SubscriptionService {
    public void subscribe(String topic, String email) {
        if (isEmailValid(email)) {
            // subscribe
        }
    }
    
    // By copying and pasting an existing class, 
    // we have introduced some duplicated code in the codebase.
    private boolean isEmailValid(String email) {
        String pattern = "email pattern";
        Pattern pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(email);
        return matcher.matches();
    }
}
class EmailValidator {
    public boolean isValid(String email) {
        String pattern = "email pattern";
        Pattern pattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(email);
        return matcher.matches();
    }
}

class UserService {
    public void createUser(String email, String password) {
        if (EmailValidator.isValid(email)) {
            // create user ...
        }
    }
}

class SubscriptionService {
    public void subscribe(String topic, String email) {
        if (EmailValidator.isValid(email)) {
            // subscribe ...
        }
    }
}

Example of "similar to"

The Template Method Pattern is a common technique for removing higher-level duplication.

interface PageRenderer {
    void renderPage();
}

class HomePage implements PageRenderer{
    private void showHeader() {
        System.out.println("<header />");
    }

    private void showNavigation() {
        System.out.println("<nav />");
    }

    private void showFooter() {
        System.out.println("<footer />");
    }

    private void showBody() {
        System.out.println("Content of home page");
    }

    @Override
    public final void renderPage() {
        showHeader();
        showNavigation();
        showBody();
        showFooter();
    }
}

class DetailPage implements PageRenderer{
    private void showHeader() {
        System.out.println("<header />");
    }

    private void showNavigation() {
        System.out.println("<nav />");
    }

    private void showFooter() {
        System.out.println("<footer />");
    }

    private void showBody() {
        System.out.println("Content of detail page");
    }

    @Override
    public void renderPage() {
        showHeader();
        showNavigation();
        showBody();
        showFooter();
    }
}

interface PageRenderer {
    void renderPage();
}

abstract class PageTemplate implements PageRenderer {
    private void showHeader() {
        System.out.println("<header />");
    }

    private void showNavigation() {
        System.out.println("<nav />");
    }

    private void showFooter() {
        System.out.println("<footer />");
    }

    protected abstract void showBody();

    @Override
    public final void renderPage() {
        showHeader();
        showNavigation();
        showBody();
        showFooter();
    }
}

class HomePage extends PageTemplate {
    @Override
    protected void showBody() {
        System.out.println("Content of home page page");
    }
}

class DetailPage extends PageTemplate {
    @Override
    protected void showBody() {
        System.out.println("Content of home detail page");
    }
}

Example of "duplication of implementation"

public class ProductRepository {
    public boolean insert(Product product) {
        Session session = null;
        try {
            session = getConnection();
            session.getTransaction().begin();
            session.save(product);
            session.getTransaction().commit();
            return true;
        } catch (HibernateException ex) {
            log.error("Failed to save product", ex);
            return false;
        } finally {
            closeConnection(session);
        }
    }
}

public class OrderRepository {
    public boolean insert(Order order) {
        Session session = null;
        try {
            session = getConnection();
            session.getTransaction().begin();
            session.save(order);
            session.getTransaction().commit();
            return true;
        } catch (HibernateException ex) {
            log.error("Failed to save order", ex);
            return false;
        } finally {
            closeConnection(session);
        }
    }
}

Solutions: using Generic class or AOP.

// Using generic class
public class CrudRepository<T> {
    public boolean insert(T entity) {
        Session session = null;
        try {
            session = getConnection();
            session.getTransaction().begin();
            session.save(entity);
            session.getTransaction().commit();
            return true;
        } catch (HibernateException ex) {
            log.error("Failed to save " + entity.getClass().getCanonicalName(), ex);
            return false;
        } finally {
            closeConnection(session);
        }
    }
}

// Using AOP Framework like AspectJ or Spring AOP
@Transactional
public class CrudRepository<T> {
    
    private EntityManager em;
    
    public boolean insert(T entity) {
        em.save(entity);
    }
}

PreviousYAGNI PrincipleNextFail Fast principle

Last updated 2 years ago