Reducing Code Dependancy between layers/classes

The concept of programing to an interface or to an abstration is well known and understood. But when it comes to actual implementation lot of mistakes are made. Here I will try to show an example of how “The Dependency Inversion Principle” as suggested by Robert C. Martin.

Basically it helps reduce 3 things i.e. RFI (Rigidity, Fragility, and Immobility) of your code.

Robert C. Martin states that the three defining factors of “bad code” are:

  1. It is hard to change because every change affects too many other parts of the system (Rigidity)
  2. When you make a change, unexpected parts of the system break (Fragility)
  3. It is hard to reuse in another application because it cannot be disentangled from the current application (Immobility)

How do you fix these problems:

1. Any high level or low level component should be dependent on abstraction and not concrete implementations.

2. Abstractions should not depend upon details of your implementation. Interface or an abstraction should cater to the common functionality of your business logic and the lower level modules.

Example:

package example;

public class Account{

    SavingsAccount savingsAccount= new SavingsAccount();

    public void newAccount(Customer customer) {
        SavingsAccount.create(customer);
    }

    class SavingsAccount{
        public void create(Customer customer) {
            //TODO: your implementation 

        }
    }

}

In this example, the Account class is directly dependent on SavingsAccount, which has no abstractions and is the implementing class.

A better way of writing the same code would be:

1. Create an interface Account.

package example;

public interface IAccount{

    public void create(Customer customer) ;

}

2. Implement IAccount:

package example;

public class SavingsAccount implements IAccount{.
public void create(Customer customer) {
            //TODO: your implementation 

        }   
}

3. Implement Account:

package example;

public class Account{

    IAccount account= null;

    public void setAccountType(IAccount account) {
        this.account= account;
    }

    public void newAccount(Customer customer) {
        account.create(customer);
    }

}

As we can see, we have decoupled the invocation from the actual implementation that is your business logic.  Any changes in your acount type class wil not affect the implementation whioch could be a third party.so you are now not breaking the high level code. According to the rules of DIP, this is all we need in order to get rid of RFI in the code.

Advertisements