Code limit 10.20.300

For any intermediate developer It is comparatively easy to write any block of code as per the requirement or business logic but the things which needs to be targeted first while writing code includes readability, testability and maintainability.

Every new developer might have done a mistake of dumping lot of code in one method or lot of irrelevant code in one class. Some automatic code analysis tools like SonarQube can warn us to reduce method lines up to 30 or reduce lambada expression lines or limit cases in switch block etc.

10-20-300 has following interpretation,

10 : Strictly no more than 10 attributes in any class.
20 : Strictly no more than 20 lines in any method.
300 : Strictly no more than 300 lines in any class.

10-20-300 rule can stop from dumping more code in any class and can ask developer to look for an alternative or it sometimes just sends a signal “time to re-factor”.

To be honest, such things can not be followed too strictly or can not be considered as a rule of thumb. This does not make you write maintainable or readble code but as you limit your code at first place, it will start making difference gradually.

This digits should trigger that you are moving in a way to increase the possibility of creating problem in either maintainability or readability. Because no developer praise the code which is hard to modify and difficult to interpret. This digits are totally based on my experience and does not have any concrete research base. The effectiveness of digits can vary up to some point as per the scenarios or use cases.

Volatile with example

Volatile is ignored or most of the times unknown concept among developers as we never(or hardly) use this keyword while building the programs.

I will try to express it in a simple term with an understandable (at least according to me) example. Before that volatile means (in Java context) liable to change rapidly.

Before volatile, we should understand why we need volatile. You know, each thread has it’s own stack (for optimization) where it can store variable used in it.

Now when variables are used among multiple threads it may be possible that one thread change the value and second would still use the old value which it has in it’s stack. Confusing!? if yes, then consider it like, each thread has it’s own memory to manipulate those variable and for the optimization sake it should not refer to the changes made by other threads.

So, what volatile keyword does ? It enforces “Java Memory Management Mechanism” to ensure that every thread can get a consistent value. Does that makes sense ? Indeed, I guess. But wait! volatile is not similar to synchronization and you can figure out that now.

Please refer to the following example.

class Counter extends Thread {
	
	private volatile long number = 0;
	
	@Override
	public void run() {
		while(number >= 0) {
			number++;
		}
		
		System.out.println("Counter is terminated! Number must be volatile.");
	}

	void terminate() {
		number = -999999999;
	}
}

class Tester extends Thread {

	@Override
	public void run() {
		Counter counter = new Counter();
		counter.start(); 

		try {
			System.out.println("Terminating the counter in 3 Seconds...");
			Thread.sleep(3000);
			counter.terminate();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

public class VolatileDemo extends Thread{

	public static void main(String[] args) {
		Tester tester = new Tester();
		tester.start();
	}
}

We will get following output with volatile

Terminating the counter in 3 Seconds...
Counter is terminated! Number must be volatile.

and following without volatile, (without volatile the program will keep on executing, so better to terminate it forcefully after observing the result for sometime.)

Terminating the counter in 3 Seconds...

To the best of my knowledge, use of volatile is too rare in day to day development. But it’s one of the hot topics in interviews due to it’s behavior.

Do you choose to throw NPE ?

Well, NPE the NullPointerException is quite famous among Java programmers. It has a bad impression although, no one want to see this in console but everyone for sure see this more than once while programming.

The agenda of this blog is whether we should throw NPE explicitly or not. Throwing exception is always better than swallowing it with try-catch and even more empty catch block is the worst thing you could have in your program.

Throwing NPE explicitly is valid, however, if you are getting something null in method parameter than we have another suitable exception which can be much more suitable and that is IllegalArgumentException.

According to the documentation, NPE is about depicting the use of null reference in program which is detected at runtime by JVM. If you could detect whether something is null in your program and want to throw NPE you are not raising it because of illegal use of null reference and actually throwing it before that.

So, we should always throw IllegalArgumentException instead of NPE if possible. I believe you will always go with this exception instead of NPE, but kindly note that throwing NPE is not a bad practice at all. Ultimate goal is to make your system report immediately if anything goes wrong instead of just continuing the execution.

Here better not to create a custom exception for such cases. Because if we already have inbuilt exception than why to create our own, so, don’t reinvent the wheel.

Declare less variables

Almost every java programmer had heard this statement “accomplish this task with less number of variables.” I sometimes think, why do we do this. I am not saying create more number of variables than needed. I am saying what does it make a difference if I complete task with two variables instead of one. Specifically, talking about interviews, almost 80% interviewer check how optimized code interviewee can write. I think that is really important in interview.

But this should not become our bad habit in professional software development. I think we should not sacrifice clarity of code for micro optimizations. Nowadays, we are living in time where we have strong servers and enough memory to handle such extra stuff. Only goal is to write maintainable code and that can be achieved by following three steps.

  1. Correctness
  2. Clarity
  3. Code optimization

Sometimes, developer becomes much more eager to write as optimized code as possible. So, code becomes difficult to maintain and sometimes quite confusing for other developers.

Why developers fail to choose readability is difficult to say. Usually, they directly jump to write code without much thinking about readability and maintainability. Nowadays, developers who write readable code are respected everywhere than those who can do much more complex and difficult task but with messy code. It can be possible to cover this in peer to peer code review. However, more then 50% of the probable bugs or convention related issues can be easily solved by tools like SonarQube, FindBugs etc.

Optimization is important but not the first goal of any real world applications. If you can write easily understandable code, optimization would be less tricky. This is what Donald Knuth said,

Premature optimization is the root of all evil.

Swap array elements

Java does not have any direct method to swap array elements. We have to create function like following. For primitive type array we have to create individual function for each type. Consider following function which swap elements in int array.

public void swap(int[] arr, int index1, int index2) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

Here we have to introduce one temporary variable to perform swap. But for array of wrapper classes we can create generic function for swapping. Following program illustrates the generic function for swapping elements of any Object array.

public <T> void swap(T[] arr, int index1, int index2) {
    T temp = arr[index1];
    arr[index1] = arr[index2];
    arr[index2] = temp;
}

As above function should have checks to disallow operation for null array and for negative index value. Otherwise caller of the method may face IndexOutOfBoundsException or NullPointerException. Moreover, we can use Collections.swap(list, index1, index2) for swapping elements of list, if we can convert our array to list.

Following function will swap the elements with swap method of Collections. But it has extra overhead of converting array to list and then list to array.

@SuppressWarnings("unchecked")
public <T> void swap(T[] arr, int index1, int index2) {
    List<T> list = Arrays.asList(arr);
    Collections.swap(list, index1, index2);
    arr = (T[]) list.toArray();// Raise unchecked casting warning
}

Left Shift Operator

Java allows bit shifting feature on integral type data. Shift operators are not used much in everyday programming task. But for interviews, questions of shift operators might be there. Before understanding what left shift does we first have to understand that how does integral data stored in Java. Note once again that only integer values can be left shifted in Java. Left shift operator is declared as ‘<<‘  (two less than characters) in java.

For integer number 10, it is stored in 4-bytes.

00000000 00000000 00000000 00001010

Now when you use left shift operator i.e 10 << 1 it will shift one bit to left. Now, number is stored like this,

00000000 00000000 00000000 00001010 : 10
00000000 00000000 00000000 00010100 : 10 << 1 = 20

So, now value 10 becomes 20 (for binary 10100). If we want to shift by 2 bits like 10 << 2, then number will be 40 (for binary 101000),

00000000 00000000 00000000 00001010 : 10
00000000 00000000 00000000 00101000 : 10 << 2 = 40

Similarly if we shift number 10 by 3 bits it will become 80. So here we can conclude that left shift works according to following formula,

number * 2 ^ shiftBitCount

Note here that left shift operator is signed operator and so it preserves the sign of the number during shift. For negative number say -10 the binary representation in 4 bytes will be 2’s complement of 10,

For number 10 we will do 1’s complement and add 1 to it,

 11111111 11111111 11111111 11110101 : 1's complement of 10
+00000000 00000000 00000000 00000001 : +1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 11111111 11111111 11111111 11110110 : -10

Let’s perform shift operation on -10 << 1,

1111111 11111111 11111111 111101100 : -10 << 1 = -20

Notice that while shifting we are padding zeros to the right and the shifted bits are lost in the space forever. Here the same formula applies and other than that the sign of the number is preserved by the left shifting operation.

Following Java program can elaborate the stated logic, kindly visit to my Number To Binary Hexa Octa String for basic introduction about Integer#toBinaryString.

public class LeftShiftOperator {
    public static void main(String[] args) {
          int ten = 10;
          System.out.println("Binary of " + ten + " : " + Integer.toBinaryString(ten));
          ten = ten << 1;
          System.out.println("Binary after left shift : " + Integer.toBinaryString(ten));
          System.out.println("Shift Result of positive : " + ten);

          int minusTen = -10;
          System.out.println("Binary of minus " + minusTen + " : "+ Integer.toBinaryString(minusTen));
          minusTen = minusTen << 1;
          System.out.println("Binary after left shift : "+ Integer.toBinaryString(minusTen));
          System.out.println("Shift Result of negative : " + minusTen);
    }
}

Above program will give us following output,

Binary of 10 : 1010
Binary after left shift : 10100
Shift Result of positive : 20
Binary of minus -10 : 11111111111111111111111111110110
Binary after left shift : 11111111111111111111111111101100
Shift Result of negative : -20

Left shift can only be performed on integer value we can do the shift on byte, short and char as well after casting them to int value. Because all the stated types are internally represented as an integer data.

Apparently, for shifting the auto-unboxing also takes place for wrapper class of int, Integer.

Integer ten = new Integer(10);
ten = ten << 1;//It's valid due to auto-unboxing

One more thing to note is that the left shifted bits are gone and never return back or can not be used any further for our integer value. So for large number if we shift them left the value may give you small negative value.

For example Integer.MAX_VALUE,

01111111111111111111111111111111 : Integer.MAX_VALUE
1111111111111111111111111111110 : Integer.MAX_VALUE << 1 = -2

Comparator in Java8

Comparator is comparatively easy to use in Java8. Functional style of programming in Java8 has introduced new way to use the comparator.

This is what we we do before Java8. Kindly note that getDob() method returns date of birth of a Student, which is java.util.Date instance.

studentList.sort(new Comparator<Student>() {

     @Override
     public int compare(Student o1, Student o2) {
         return o1.getDob().compareTo(o2.getDob());
     }
});

Here we can see that we have to create the anonymous class of comparator and then we provide the sorting logic.  With Java8 we can use Lambada expression to reduce the extra boiler plate code of comparator declaration and compare method declaration.

studentList.sort((o1, o2) ->  {
    return o1.getDob().compareTo(o2.getDob());
});

You can see how it is reduced in size. Even more there are lot of default methods has been introduced in Comparator interface. For example,

studentList.sort(Comparator.comparing(Student::getDob));

Here comparing method will prepare the comparator based on the method reference we have provided. Moreover, we can also simply reverse the order of sorting,

studentList.sort(Comparator.comparing(Student::getDob).reversed());

Lot more default methods are there in Comparator interface to reduce the extra code of comparator declaration and speed up the development.