Tag Archives: Java

Clean Code: Error Handling, Testing, and Classes

In the clean code series, I will cover Error Jandling, Testing and Clean classes in this post.

Error Handling

  • Catch only Exceptions meant to be caught, for example, checked exceptions in Java
  • Log as much information as possible when an error or exception occurs for analysis
  • Null objects should not be returned, instead, return empty objects

Testing

  • Code Coverage targets should be set and achieved
  • TDD helps write testable code and reduce the number of issues
  • Use the F.I.R.S.T rule for testing:
    • The test is fast-running.
    • The tests are independent of others.
    • The test is repeatable in various environments.
    • The test is self-validating.
    • The test is timely.

Clean Class

  • Single Responsibility
  • Open for extension and closed for Modifications
  • Readability: self-documenting class names, function names, and variable names

Clean Code: Comments, Formatting, and Objects

In continuation with the clean code series, here I am covering Comments, Formatting, and Objects and data structures.

Comments

  • Code should be self-explanatory, the purpose of the code is that humans should be able to understand and not that computer is able to execute it
  • Comment only where logic is complex
  • Private API should not have comments
  • Use comments when you want to caution other developers, for example, why List instead of Queue was chosen and should not be modified
  • Comments should answer why (was a decision made) and not how the code works

Formatting

  • Formatting is a way to communicate with fellow developers
  • Readability = Maintainability = Extensibility
  • Verticle Alignment: Keep connected functions together for better readability
  • Horizontal Alignment: one should never need to scroll right
  • Team Formatting Rules: everyone should follow the same rules, braces, ident size, spaces/tabs

Objects and Data Structures

  • Follow OOPS Principles, e.g. parameters and behavior should be encapsulated
  • Law of Demeter:  M method of an object O can only consume services of the following types of objects:
    • The object itself, O.
    • The M parameters.
    • Any object created or instantiated by M.
    • Direct components of O.
  • Avoid Static methods wherever possible

Clean Code: Naming and Functions

Inspired by Clean Code by Robert C Martin, trying to summarize coding best practices. Starting with Naming and Functions best practices in this post.

Naming

  • Names should encode the intent, for example, studentBirthYear.
  • Use Good distinction: Do not use list1, list2, etc
  • Use Pronounceable name: dobmmyy vs dateOfBirthInMonthAndYear
  • use searchable names: int i, j, when you will try to search you will find a lot of them in code
  • Do not add type: phoneString, name String, name and phone should be sufficient
  • Avoid unclear prefixes: m_name vs manager_name
  • nouns for names and verbs for functions: employee for class and paySalary for function
  • Use Consistent concept: controller vs manager
  • Don’t use the same name twice to mean 2 different things. paymentInfo at one place returns bank details and another place user payment
  • Use Domain specific names
  • Avoid too long or too short names: Long is fine if it conveys better information, but not too long that makes it difficult to pronounce

Functions

  • Write Small functions, functions larger than 20 lines should be avoided
  • Make sure the function does only one thing
  • Use minimum arguments: max 2, if the function takes too many arguments, it is doing too much
  • DRY, Do not Repeat yourself: IF you are doing the same thing in multiple functions, move it to commonplace
  • Don’t use flag element, parameters of the Boolean type as a parameter already clearly state that it does more than one thing.

Java Modules

Modularization introduced in Java 9 is to help developers call out explicitly what are they going to use in their application and what features are they ready to expose.

You can see that JDK itself now is viewed as a combination of modules rather than a single monolith unit. One can mention all modules they are going to use in the application and keep the application lightweight. This can be done by adding a “requires” section in the module-info file.

Another problem Modules solve is when you are sharing your library (a jar), it exposes all the packages, though you might not want users to play around with internal helper files. The “exports” keyword gives you control over what is being exposed from the package.

Sample module-info.java

module java.mymodule {
  requires java.sql;
  exports java.util.string;
}

Recommended Reading

Collection Framework

Sometime back I wrote about Collections Framework. Here let me take a slightly deeper look into some of the concrete implementations with examples.

Hierarchy of the Collection Framework
https://www.geeksforgeeks.org/collections-in-java-2/

List Implementations

ArrayList: Simply put, this provides dynamic array implementation in Java.

LinkedList: Implementation of Linked List data structure. Provides methods like add and remove.

Vector: It is a synchronized ArrayList.

Stack: Implementation of Stack data structure. Provides methods like push and pop.

Queue Implementations

PriorityQueue: Implement First In, First Out. If Comparator is provided, it will be used for Priority management.

public class PriorityQueueDemo {
    
  public static void main(String args[])
  {
      PriorityQueue<Integer> pQueue = new PriorityQueue<Integer>();

      pQueue.add(10);
      pQueue.add(20);
      pQueue.add(15);

      System.out.println(pQueue.peek());
      System.out.println(pQueue.poll());
      System.out.println(pQueue.peek());
  }
}

Output

10
10
15

Dequeue Implementation

ArrayDequeue: Double-ended queue implementation. Provides methods like add, addFirst, addLast.

Set Implementations

HashSet: Implementation of hash table data structure. Do not guarantee order.

LinkedHashSet: Uses a doubly linked list and hence maintains the order.

Sorted Set Implementation

TreeSet: Ordering is maintained as natural order or explicit comparator based ordering.

public class TreeSetDemo {  
  public static void main(String args[])
  {
      TreeSet<String> ts = new TreeSet<String>();

      ts.add("this");
      ts.add("is");
      ts.add("just");
      ts.add("a");
      ts.add("test");

      Iterator<String> itr = ts.iterator();
      while (itr.hasNext()) {
          System.out.println(itr.next());
      }
  }
}

Output

a
is
just
test
this

Java Collection Framework and Generics

As the name suggests, a Java Collection is a collection of objects represented as a single unit. The idea is to provide a set of operations on the logically grouped elements like searching, sorting, etc.

collection framework hierarchy
source: https://techvidvan.com/tutorials/java-collection-framework/

As the image above shows, there are two core interfaces, Collection and Map. The collection further has interfaces for List, Queue, and Set. For each of these interfaces than we have a concrete set of classes implementing the functionality.

Let’s take a very simple example

Collection values = new ArrayList();
values.add(1);
values.add(2);
values.add("kamal");

We can see collection interface helps us create a new ArrayList, which gives us flexibility over the array where the List can grow during runtime.

But one challenge we can see in the code above is that when we are able to add numbers as well as String to the ArrayList. This is in contrast with the type safety provided by Java. To solve this Java provides us Generics to control over types of elements that can be added to a collection.

Generics Example

class MyClass<T>{
T value;

public T getValue() {
return value;
}

public void setValue(T value) {
this.value = value;
}
}

Coming to our previous code for creating collections

Collection<Integer> values = new ArrayList<>();
values.add(1);

In this example, we cannot add a String to values now.

What if we want to get or add into ArrayList at a particular index. List Interface adds these features on top of Collection. As already depicted in the hierarchy, List inherits Collection and then adds features on top of it.

List<Integer> values = new ArrayList<>();
values.add(1);
int num = values.get(0);

Iterating over a Collection

There are multiple ways to iterate over a collection

List<Integer> values = new ArrayList<>();
values.add(1);
values.add(2);
values.add(3);
Iterator<Integer> i= values.iterator();
while(i.hasNext()) {
    System.out.println(i.next());
}

Another way is to use for loop

for(Integer num:values) {
   System.out.println(num);
}

Or we can use Streams

values.stream().forEach(System.out::println)

Comparable vs Comparator

Another important thing one would like to do with the collection is to arrange elements in sorted order. For example, say we have a List created for Student class objects, and we want to arrange based on Roll numbers.

The easiest way is to make the class implement comparable

class Student implements Comparable<Student>{

 int rollno;
 String name;

 public Student(int rollno, String name) {
  this.rollno=rollno;
  this.name=name;
 }

 @Override
 public int compareTo(Student o) {
  return this.rollno<o.rollno?-1 : (this.rollno==o.rollno)?0:1;
 }
}

// In calling code, we can sort list made up of students 
Collections.sort(list);

There can be cases where it is handy to maintain comparison based on multiple criteria. For example, along with roll number, we want to make sure we can sort the list of students based on names in alphabetical order. In such a case it makes sense to implement Comparator as we can implement multiple comparators based on our need.

class NameComparator implements Comparator<Student>{
 @Override
 public int compare(Student o1, Student o2) {
  return o1.name.compareTo(o2.name);
 }
}

// In calling code, we will send compatator instance 
Collections.sort(list, new NameComparator());

Getting started with Spring Boot

This is a short tutorial about creating a simple REST webservice with spring boot. This assumes you have basic knowledge of Spring and Java.

To get started we will create a Spring project. The simplest way to do this is to go to http://start.spring.io/ and create a project.

This will give us a blank project on which we can build upon. Import the project as Maven project to Eclipse or any other ID. By default, it will provide a class which will look like

@SpringBootApplication
public class NewtestApplication {

	public static void main(String[] args) {
		SpringApplication.run(NewtestApplication.class, args);
	}
}

As you can see this is the main class and all the execution starts here. Also, note the @SpringBootApplication annotation. Spring documentation states that

“The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan with their default attributes”

For this example, we will keep it simple and introduce a controller

@RestController
public class HelloController {
	
	@GetMapping("/sayhello")
	public String sayHello() {
		return("Hello");
	}
}

Finally, Run the main class as a normal Java application, it will automatically start the Spring Boot server at 8080.

We can now access our application at http://localhost:8080/sayhello

Updating Java version in Linux

Recently I upgraded my Java version from 9 to 10 on a Linux machine. I was able to set JAVA_Home in .bashrc file properly but version did not get updated when checked java -version on shell.

Following commands helped to change the system’s Java version

sudo update-alternatives --install "/usr/bin/java" "java" "/path/to/jdk-10.0.1/bin/java" 1

And then

sudo update-alternatives --config java

This showed all the Java versions available and I was able to choose correct version i.e. 10.
Similary executed same commands for java compiler.

sudo update-alternatives --install "/usr/bin/java" "java" "/path/to/jdk-10.0.1/bin/javac" 1
sudo update-alternatives --config javac