Skip to main content

Single Responsability Principle

The Single Responsibility Principle states that a class should have only a single responsibility. A class can do a simple job or a complex job, but if it's designed to carry many responsibilities it can increase the possibility of bugs. 

This principle is focused on separating behaviors so that if a bug comes up it won't affect other unrelated behaviors.

Suppose that you are building a class CustomerSearch as shown below.


public class CustomerSearch {
    
    private ArrayList<Customer> customers = new ArrayList<>();

    public CustomerSearch() {
        this.customers.add(new Customer("Great Lake","USA","NYC"));
        this.customers.add(new Customer("The Dog","USA","Chicago"));
        this.customers.add(new Customer("The Jam","USA","Seattle"));
        this.customers.add(new Customer("The Box","Japan","Tokyo"));
    }
    
    public ArrayList<Customer> searchByCounty(String country){
        ArrayList<Customer> result = new ArrayList();
        for (Customer customer : customers) {
            if (customer.getCountry().equals(country)){
                result.add(customer);
            }
        }
        return result; 
    }
    
}


As you can see the class has a public method: searchByCountry(country). This method is in charge on returning the search results as a list of Customer objects.

Now let's say that we need to export those results. To complete this assignment let's say you modify the CustomerSearch class as shown below.

public class CustomerSearch {

    private ArrayList<Customer> customers = new ArrayList<>();

    public CustomerSearch() {
        this.customers.add(new Customer("Great Lake","USA","NYC"));
        this.customers.add(new Customer("The Dog","USA","Chicago"));
        this.customers.add(new Customer("The Jam","USA","Seattle"));
        this.customers.add(new Customer("The Box","Japan","Tokyo"));
    }
    
    public ArrayList<Customer> searchByCounty(String country){
        ArrayList<Customer> result = new ArrayList();
        for (Customer customer : customers) {
            if (customer.getCountry().equals(country)){
                result.add(customer);
            }
        }
        return result; 
    }
    
    
    public void csvExport(ArrayList list) throws IOException{
        try (CSVWriter writer = new CSVWriter(new FileWriter("./test.csv"))) {
            writer.writeAll(list);
        }
    }
}

The CustomerSearch class now has an additional method csvExport(). This design seems quite normal but it's a flawed design. Now, this class has two responsibilities and might cause problems in the future. Let's say that now we want to export to PDF, in that case, you would need to modify the CustomerSearch class again and can cause changes in previous functionalities. Any change in the CustomerSearch class may need testing to ensure that the changes did not affect the rest of the application.

This design issue can be corrected if the CustomerSearch class is designed to adhere to the Single Responsibility Principle as shown below.

CustomerSearch Class

public class CustomerSearch {

    private ArrayList<Customer> customers = new ArrayList<>();

    public CustomerSearch() {
        this.customers.add(new Customer("Great Lake","USA","NYC"));
        this.customers.add(new Customer("The Dog","USA","Chicago"));
        this.customers.add(new Customer("The Jam","USA","Seattle"));
        this.customers.add(new Customer("The Box","Japan","Tokyo"));
    }
    
    public ArrayList<Customer> searchByCounty(String country){
        ArrayList<Customer> result = new ArrayList();
        for (Customer customer : customers) {
            if (customer.getCountry().equals(country)){
                result.add(customer);
            }
        }
        return result; 
    }
    
}


Export Class


public class Export {
    public void csvExport(ArrayList list) throws IOException{
        try (CSVWriter writer = new CSVWriter(new FileWriter("./test.csv"))) {
            writer.writeAll(list);
        }
    }
}


The modified design has two independent classes CustomerSearch and Export class. This way both classes only have one responsibility. If you want to add a different way to export data, you would modify the Export class only and the CustomerSearch class remains unaffected. 

Reference

Joshi, B. (2016b). Beginning SOLID Principles and Design Patterns for ASP.NET Developers (English Edition) (1st ed.). Apress.

Comments