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);
    }
}

Last updated