Dealing Cyclomatic Complexity in Java Code

Dealing Cyclomatic Complexity in Java Code Debadatta Mishra Introduction You may have heard the term code management in java. It refers to how to manage your source code so that it may be easier to a certain extent to deal with it at the time of maintenance. It is always true that requirements change from time to time and source code undergoes a change to a certain extent. You may have seen some particular module seems very risky to touch. Some people say that this module is working fine but code is unmanageable. It happens in most of the IT industry, there may be several reasons. However I can say writing code is an art. Some developers take this matter very seriously. You may find the occasion of code review and code audit in the organization. How to write the better code is beyond the scope of this article. In this article I would like to focus on the cyclomatic complexity which is much more prevalent in the source code. It is also true that you can keep yourself aloof from this concept. The key note is how to deal with the code complexity.

Technicalities

Cyclomatic Complexity is concept on metric which was coined by Thomas McCabe. It gives the notion of structural complexity of a method or source code. Basically it deals with the various decisional and conditional cases. If you are writing a piece of code that includes several logical decisions and conditions, you have to take care of that piece of code otherwise you may find yourself in a dwindling conditions. The main reason I can say that it happens due to bug fixing and some minor requirement change. If a developer forgets some of the functional cases, he/she can fix a bug by adding one or more logical conditions by writing if or nested if conditions. Generally cyclomatic complexity can be calculated in the following manners.

Cyclocmatic complexity = Number of decision points + 1 The decision points may be your conditional statements like if, if … else, switch , for loop, while loop etc.

Please refer to the following example String str = “someString”; if ( str.equals( case1 ) ) do something; if( str.equals( case2 ) ) do something; else do default thing;

Here the cyclomatic complexity will be as follows Cyclomatic Complexity = if for case1+if for case2+else+1=4 Cyclomatic complexity has more significance on the field of testing and maintainability. If you are writing test cases, you have to keep an eye on the cyclomatic complexity. If the cyclomatic complexity is 3, you have to write e valid test cases at least. The following chart describes the type of the application. Cyclomatic Complexity lies 1 – 10  To be considered Normal applicatinon Cyclomatic Complexity lies 11 – 20  Moderate application Cyclomatic Complexity lies 21 – 50  Risky application Cyclomatic Complexity lies more than 50  Unstable application Besides logical operators like “&&”, “||” are also addition to the cyclomatic complexity. If you are writing the program like the following If( name.equals(name1) || name.equals( name2 ) || name.equals( name3) && age != 23 ) { do something } Here Cyclomatic Complexity can be calculated as follows Number of decion points + number of logical operators + 1 which is equal to If+ ||+||+&&+1 = 5 It is also true that it will have impact on the performance of the application. However you may seen in a certain design, there may be several cases and each case has to be handled in a completely different way, some developers write using factory design. In that factory design there may be either switch case or several if else conditions. Let me give an example. Let us consider a Handler which handles completely different based upon the input. If the case is “A” it should be handled in a particular way, if it is case “B”, it should be handled in an another way. Let us look into the following piece of code.



Interface Handler

package com.core.cc.handler;

/**
 * @author Debadatta Mishra(PIKU)
 *
 */
public interface Handler 
{
	public void handle();
}
Class AHandler

package com.core.cc.handler;

/**This class implements Handler
 * @author Debadatta Mishra(PIKU)
 *
 */
public class AHandler implements Handler 
{
	public void handle() 
	{
		System.out.println("A handler");
	}
}
Class BHandler

package com.core.cc.handler;

/**This class implements Handler Interface
 * @author Debadatta Mishra(PIKU)
 *
 */
public class BHandler implements Handler 
{
	public void handle() 
	{
		System.out.println("B handler");
	}
	
}
class AbstractHandler

package com.core.cc.handler;

/**This class is used as a Factory class.
 * @author Debadatta Mishra(PIKU)
 *
 */
public class AbstractHandler 
{
	/**This is a very traditional method, you
	 * can obtain the dynamic object by using
	 * several if conditions.
	 * @param handlerName 
	 * @return an object of type {@link Handler}
	 */
	public static Handler getHandler( String handlerName )
	{
		Handler handler = null;
		try
		{
			if( handlerName.equals("A"))
				handler = new AHandler();
			if( handlerName.equals("B") )
				handler = new BHandler();
		}
		catch( Exception e )
		{
			System.out.println("There is no specific handler");
		}
		return handler;
	}

}
class TestDynamicHandler

import com.core.cc.handler.AbstractHandler;
import com.core.cc.handler.Handler;

/**This is a testharness class.
 * @author Debadatta Mishra(PIKU)
 *
 */
public class TestDynamicHandler 
{
	public static void main(String[] args) 
	{
		Handler handler = AbstractHandler.getHandler("B");
		handler.handle();
	}

}

In the above examples, there is nothing wrong in writing the code this, but compiler may take sometime when your cases increase. For every new case, you have to write a new class and you have to add one or more if clause in the class “AbstractHandler”. You can modify the class “AbstractHandler” in the following manner so that it looks very sophisticated and thereby there is no need to update the class “AbstractHandler”.


package com.core.cc.handler;

/**This class is used as a Factory class.
 * @author Debadatta Mishra(PIKU)
 *
 */
public class AbstractHandler 
{
	/**This method is used to obtain the dynamic
	 * object of the type Handler
	 * @param handlerName
	 * @return an object of type {@link Handler}
	 */
	public static Handler getHandler( String handlerName )
	{
		Handler handler = null;
		try
		{
			handler = (Handler) Class.forName(
					"com.core.cc.handler." + handlerName + "Handler")
					.newInstance();
		}
		catch( Exception e )
		{
			System.out.println("There is no specific handler");
		}
		return handler;
	}
}

The above code simplifies your programming and provides the flexibility to add your cases without bringing major changes. After all this is the beauty of the Java Factory Design. In this regard you can make an argument that , reflection is slower from the point of performance, I can say that it will be faster as compared to many if … else clause. However there are several ways you can write beautiful code to avoid major cyclomatic complexity.

Conclusion

I hope that you will enjoy my article. If you find any problems or errors, please feel free to send me a mail in the address

debadattamishra@aol.com

. This article is only meant for those who are new to java development. This article does not bear any commercial significance. Please provide me the feedback about this article.

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more