Search code examples
javaintellij-ideamethodsrefactoringcode-duplication

Refactoring functions with nearly entirely duplicate code but different calls to other methods


I'm learning Java and I'm in the middle of online courses and such, and I'm on one of the coding exercises and realized there is a whole lot of duplication between my two methods, found below:

private static void addCustomerTransaction() {
    System.out.println("Enter the branch name:");
    String branchName = scanner.nextLine();

    System.out.println("Enter the customer name:");
    String customerName = scanner.nextLine();

    System.out.println("Enter the transaction");
    while (!scanner.hasNextDouble()) {
        scanner.next();
    }
    double transaction = scanner.nextDouble();

    bank.addCustomerTransaction(branchName,customerName,transaction);

}

private static void addCustomer() {
    System.out.println("Enter the branch name:");
    String branchName = scanner.nextLine();

    System.out.println("Enter the customer name:");
    String customerName = scanner.nextLine();

    System.out.println("Enter the transaction");
    while (!scanner.hasNextDouble()) {
        scanner.next();
    }
    double transaction = scanner.nextDouble();

    bank.addCustomer(branchName,customerName,transaction);
}

Now obviously the only difference between these two functions is the method call to a bank class object - which end up performing different actions.

I'm wondering how I could refactor these methods so that there is reduced duplication. I get as far as:

private static void addCustomerTransaction() {
    customerInput();

}

private static void addCustomer() {
    customerInput();
}

private static void customerInput() {
    System.out.println("Enter the branch name:");
    String branchName = scanner.nextLine();

    System.out.println("Enter the customer name:");
    String customerName = scanner.nextLine();

    System.out.println("Enter the transaction");
    while (!scanner.hasNextDouble()) {
        scanner.next();
    }
    double transaction = scanner.nextDouble();

    bank.addCustomerTransaction(branchName,customerName,transaction);
}

But I've no idea how to enable the code to change the method call (currently bank.addCustomerTransaction(branchName,customerName,transaction); in the customerInput function according to which function is calling the customerInput.

Could anyone advise on the next step?


Solution

  • Here is one option.

    Create an interface for the last method:

    @FunctionalInterface public interface CustomerOperation {
      void apply(Bank bank, String branch, String customer, String transaction);
    }
    

    Then your common method can look like this:

    private static void customerInput(CustomerOperation operation) {
      //common code here
      operation.apply(bank, branchName, customerName, transaction);
    }
    

    And you call it like this:

    private static void addCustomerTransaction() {
      customerInput((bank, branchName, customerName, transaction) ->
          bank.addCustomerTransaction(branchName, customerName, transaction));
    }
    
    private static void addCustomer() {
      customerInput((bank, branchName, customerName, transaction) ->
          bank.addCustomer(branchName, customerName, transaction));
    }
    

    Or using method references:

    private static void addCustomerTransaction() {
      customerInput(Bank::addCustomerTransaction);
    }
    
    private static void addCustomer() {
      customerInput(Bank::addCustomer);
    }