Coupling in Java


Coupling in Software Architetcure

“Software application developed in 2 years, but the maintenance for the application spans for 20 years”.

 “80% of the software engineers maintain the code already written by someone”.

Simple modifiable understandable software design and architecture

The industry research data shows the importance of writing the code which is easy to manage, simple to understand and allow changing the application for the new requirements. Industry moves from procedural programming to object oriented programming for these attributes. So designing application architecture, we have to consider all these quality factors to make application easier. Let us have a simple interest calculation module. Assume that we would create a module to calculate the simple interest calculation and share the jar to other user to make use of it.

Package com.javaarchitectjourney

 Class InterestCalculator{

               public int principal;

               public  int years;

               public static float interestRate=1.23;

              public void calculateInterest(){

                     system.out.println(prinicipal* years*interestRate);

               }

}

Package com.caller;

Class Caller{

  Public static void main(String[] args)

           {

                InterestCalculator ic = new InterestCalculator();

                //Direct access to the local variables

               int years = 10;       ic.years = years;       ic.principal = 10000;

                ic.calculateInterest();

               //Invalid values years = -10;

               ic.years = -10;

               ic.calculateInterest();

      }

 }

This simple program would calculate the simple interest and would calculate the simple interest properly. The existing model the “years” is int type. Now we received the requirement that years should be floating point number as month has to be considered. If we change the years from “int” to “float”, all the callers should change their code to change it. The same way the caller assigns invalid values, there is no check in InterestCalculator and we are not restricting as well. For example, the caller assigns obj.years = -10;  The program would calculate the simple interest and prints value in “-“. It is illogical and blunder in the code.

To fix the above two design issues, best practices has been suggested.

1). All the local variables should be declared as “private”

2). All the local variable should be accessed by accessor methods.

Let us change the program as below,

Class InterestCalculator{

              private int principal;

              private  int years;

              private static float interestRate=1.23;

              public void setYears(int years)

                      {

                        // convert the types to different type here such as int to Integer

                       // check for the negative values and throw exception here.

                      }

}

 

We added the check  by creating the accessor methods for local variables and  make the local variable to private. In the accessor method setYears(), we can validate the years value is greater than “0” and made the years local variable accessor to “private”. Now we added the check and validation. Excellent. One minute here…!!! What would happen the API programmers who called this method?  For instance we change “years”  from “int” primitive to “Integer” type. As we decided to change our code, we can change the type and handle the “int” to “Integer” conversion in our setter() and getter() accessor methods. The caller code is intact and their code is undisrupted. This is the design we are looking for.

 

Let us assume, now two caller calls the interestCalculator.

Caller 1:

//Interest value is static and it is being shared with all the objects.

     //Changes the interest values without knowing that variable is “static” and calculate the interest

      InterestCalculataor ic1 = new InterestCalculator();

       Ic1. interestRate = 10.00;  ic.years = 10; ic.principal = 10000;

       Ic1.calculateInterest();

Caller 2:

// He is not aware of the interest rate changed by caller1 and assumes interest rate is 1.23

      InterestCalculataor ic2 = new InterestCalculator();

      Ic2.years = 10; ic2.principal = 10000;

      Ic2.calculateInterest();

Now caller2 would get the interest values that is incorrect and he has no clue as where the issue in the code. Are you able to find the issue in this code? Why caller2 is impacted and gets wrong value?

Look at code again and share your insights on this.

The problem here is the interest is shared between all the objects and that variable is not managed properly. So the module is not returning proper result. So we should not share the variables among objects and if it required we have to manage them properly such as marking them immutable as “final”.

The API programming should designed with consideration of variable access and sharing the variables among objects.  The defined pattern explained as “Coupling” for API programming. It explains that how the API should be designed and access privilege of local modifier in API programming. The above design we explored on “Content Coupling” and “Common Coupling”.

Object oriented programming and Java defines the low coupling by the term “data abstraction”,  “Encapsulation” or “data hiding”. To make aclass as abstracted,encapsulated and data hidden follow coupling standard to avoid high coupling.  All classes in the software design should be high cohesion and low coupling. in other words, highly logical and dependent classes.

 

The best API programming model should flow low coupling and high cohesion. It makes the API as simple, easy to modifiable and understandable.  None of the technology or framework makes the module easy or understandable.  Architect and programmers should design the module in a way to understandable and modifiable. It is your responsibility. Only you!!

You may also like