Google

May 30, 2014

How to create a well designed Java application? SOLID and GoF design patterns strive for tight encapsulation, loose (or low) coupling and high cohesion

A software application is built by coupling various classes, modules, and components. Without coupling, you can't build a software system. But, the software applications are always subject to changes and enhancements. So, you need to build your applications such a way that they can easily adapt to growing requirements and easy to maintain and understand. 3 key aspects to achieve this are

1. Tight encapsulation.
2. Loose (or low) coupling.
3. High cohesion.

The purpose of SOLID design principles and GoF design patterns is to achieve the above goal.


What is encapsulation?

Encapsulation is about hiding the implementation details. This means

1) Hiding data by setting member variables with private access level and providing public methods with pre and post condition checks to access the member variables.




2) Coding to interface and not implementation: Using a given class or module by its interface, and not needing to know any implementation details.

Badly Encapsulated: Directly dependent on ProductServiceImpl




Tightly Encapsulated: Dependent on the interface ProductService. The implementation can change from ProductServiceImpl to InternationalizedProductServiceImpl  without  the callers or clients OrderServiceImpl, SalesEnquiryServiceImpl, and CustomerServiceImpl  needing to know about the implementation details.





SOLID Principle:  LSP (Liskov substitution principle), DIP (Dependency inversion principle), and SRP (Single Responsibility Principle) strives to create tight encapsulation.


Q. Does tight encapsulation promote loose coupling?
A. Yes, poor encapsulation can allow tight coupling  as it will be possible to access non-encapsulated variables directly from another class, making it dependent on the implementation of the class that contains those variables. It is also possible to have poor encapsulation with loose coupling. So, encapsulation and coupling are different concepts, but poor encapsulation makes it possible to create tight coupling. 



What is coupling?

Coupling in software development is defined as the degree to which a module, class, or other construct, is tied directly to others. You can reduce coupling by defining intermediate components (e.g. a factory class or an IoC container like Spring) and interfaces between two pieces of a system. Favoring composition over inheritance can also reduce coupling.

Let's write some code for the above UML diagram to demonstrated loose coupling with GoF factory design pattern.

Step 1: Define the interfaces for the above diagram

public interface OrderService {
      abstract void process(Product p);
}


import java.math.BigDecimal;

public interface ProductService {
    abstract BigDecimal getDiscount(Product p);
}


Step 2: Define the implementation class for ProductService

public class ProductServiceImpl implements ProductService {

 @Override
 public BigDecimal getDiscount(Product p) {
  //logic goes here
  return null;
 }

}


Step 3: Factory eliminate need to bind application specific classes into the code. The code only deals with the ProductService interface , and can therefore work with any user-defined concrete implementations like ProductServiceImpl or InternationalizedProductServiceImpl.

public final class ProductServiceFactory {
   
 private ProductServiceFactory(){}
 
 public static ProductService getProductService() {
  ProductService ps = new ProductServiceImpl(); // change impl here
  return ps;
 }
}


Step 4: The caller or client class who is loosely coupled to ProductService via the ProductServiceFactory.

import java.math.BigDecimal;

public class OrderServiceImpl implements OrderService {
 
 ProductService ps;
 
 @Override
 public void process(Product p) {
  ps = ProductServiceFactory.getProductService();
  BigDecimal discount = ps.getDiscount(p);
  //logic
 }

}

So, if you want to change over from ProductServiceImpl  to  InternationalizedProductServiceImpl, all you have to do is make a change in the ProductServiceFactory class. An alternative approach to using a factory is to use an IoC container like Spring instead of a factory class to loosely wire the dependencies via dependency injection at run time.


Q. How do you create loose coupling?
A. By abstracting many of the implementation needs into various interfaces and introducing the concepts of OCP and DIP, you can create a system that has very low coupling.



What is cohesion? Cohesion is the extent to which two or more parts of a system are related and how they work together to create something more valuable than the individual parts. You don't want a single class to perform all the functions (or concerns) like being a domain object, data access object, validator, and a service class with business logic. To create a more cohesive system from the higher and lower level perspectives, you need to break out the various needs into separate classes.

Coupling happens in between classes or modules, whereas cohesion happens within a class.



Q. How do you create high cohesion?
A. You can get higher cohesion with a combination of low coupling and SRP (Single Responsibility Principle from SOLID), which allows you to  stack a lot of small pieces (e,g. Service, DAO, Validator, etc) together like puzzles to create something larger and more complex.



So, think, tight encapsulation, loose (low) coupling, and high cohesion.


Labels: ,

May 29, 2014

Event Driven Programming: Java example tutorial style - part 1

Event Driven Architecture aka EDA loosely couples event producers and event consumers.

An event can be defined as "a change in state". For example, when an event producer fires an event to notify all its registered listeners that either "securities" or "security prices" have been loaded, the listeners are notified to update their data via a synchronous or asynchronous dispatcher. Both the "Event" producers and listeners are loosely coupled via an "EventHub" and "Event". An "EventHub" is used to register and unregister listeners.

The "EventHub" can be registed as a JMX bean to control behaviors at runtime via a jconsole like firing an event, count number of events, etc.

A number of tutorials will take you through writing event driven code in Java along with registering as MBean to interact via a JMX compliant tool like jconsole.



Let's define the interfaces and implementation classes.


Step 1: Define the "Event" class from which all other events can be derived from.

package com.writtentest14;

import java.util.Date;

public class Event {

 private String id;
 private Date timeStamp;
 
 public Event(String id) {
  super();
  this.id = id;
  this.timeStamp = new Date();
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public Date getTimeStamp() {
  return timeStamp;
 }

 public void setTimeStamp(Date timeStamp) {
  this.timeStamp = timeStamp;
 }

}


Step 2: Define the interface for the listeners

package com.writtentest14;

public interface EventListener<T extends Event> {
 void onEvent(T event);
}


Step 3:  Define the dispatcher interface.

package com.writtentest14;

import java.util.List;


public interface EventDispatcher {

    void dispatch(Event event, List<EventListener<Event>> listeners);    
}


Step 4: The dispatcher implementation. It could be synchronous or asynchronous dispatcher. Let's keep it simple by defining a synchronous dispatcher.

package com.writtentest14;

import java.util.List;

public class SimpleSynchronousDispatcher implements EventDispatcher {

    @Override
    public void dispatch(Event event, List<EventListener<Event>> listeners) {
        for (EventListener<Event> listener : listeners) {
            listener.onEvent(event);
        }
    }
}

Step 5:  Define the EventHub. Binds and unbinds listeners and invokes the dispatcher to dispatch the events.

package com.writtentest14;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;

/**
 * register and unregister event listeners
 */

public class EventHub {

 private static final EventHub INSTANCE = createInstance();
 
 private ConcurrentMap<String, List<EventListener<Event>>> registeredListeners = 
                                   new ConcurrentHashMap<String, List<EventListener<Event>>>();

 private EventDispatcher synchronousDispatcher;

 private AtomicLong eventCount = new AtomicLong();

 public EventHub() {
 }

 public static EventHub instance() {
  return INSTANCE;
 }

 public EventHub(EventDispatcher synchronousDispatcher) {
  this.synchronousDispatcher = synchronousDispatcher;
 }

 public long getEventCount() {
  return this.eventCount.get();
 }

 private long getNextEventNumber() {
  return this.eventCount.incrementAndGet();
 }

 protected EventDispatcher getSynchronousDispatcher() {
  return this.synchronousDispatcher;
 }

 public void setSynchronousDispatcher(EventDispatcher dispatcher) {
  this.synchronousDispatcher = dispatcher;
 }

 public void fire(Event event) {
  dispatch(event, getSynchronousDispatcher());
 }

 public synchronized void addListener(String eventId, EventListener<Event> listener) {
  List<EventListener<Event>> listeners = this.registeredListeners.get(eventId);
  if (listeners != null) {
   listeners.add(listener);
  } else {
   listeners = new CopyOnWriteArrayList<EventListener<Event>>();
   listeners.add(listener);
   this.registeredListeners.put(eventId, listeners);
  }

 }

 public void removeListener(String eventId, EventListener<Event> listener) {
  List<EventListener<Event>> listeners = this.registeredListeners.get(eventId);
  if (listeners != null) {
   listeners.remove(listener);

  }
 }

 protected void dispatch(Event event, EventDispatcher dispatcher) {
  getNextEventNumber();
  List<EventListener<Event>> listeners = getListeners(event);
  if (!listeners.isEmpty()) {

   dispatcher.dispatch(event, listeners);

  }
 }
 
  private static EventHub createInstance() {
         EventHub instance = new EventHub(new SimpleSynchronousDispatcher());
         return instance;
     }

 private List<EventListener<Event>> getListeners(Event event) {
  List<EventListener<Event>> listeners = this.registeredListeners.get(event.getId());
  return (listeners != null) ? listeners : Collections.<EventListener<Event>>emptyList();
 }

}


Step 6: Finally, the EventHubMain that has the main method to run, and creates 3 listeners as  anonymous inner classes, and also acts as a producer to fire events. The listeners and the producer are decoupled via EventHub as the producer and listeners don't interact with each other, but via the EventHub and Event classes.

package com.writtentest14;

import java.util.concurrent.TimeUnit;

public class EventHubMain {

 private static final String PRICE_LOAD_EVENT = "PL_EVENT";
 private static final String SECURITY_LOAD_EVENT = "SL_EVENT";

 public static void main(String[] args) {

  // Anonymous listener1
  EventHub.instance().addListener(PRICE_LOAD_EVENT, new EventListener<Event>() {

   @Override
   public void onEvent(Event event) {
    System.out.println(PRICE_LOAD_EVENT + " received by listener " + this.getClass());
    try {
     TimeUnit.SECONDS.sleep(10);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }

  });

  // Anonymous listener2
  EventHub.instance().addListener(SECURITY_LOAD_EVENT, new EventListener<Event>() {

   @Override
   public void onEvent(Event event) {
    System.out.println(SECURITY_LOAD_EVENT + " received by listener " + this.getClass());
    try {
     TimeUnit.SECONDS.sleep(10);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }

  });

  // Anonymous listener3
  EventHub.instance().addListener(PRICE_LOAD_EVENT, new EventListener<Event>() {

   @Override
   public void onEvent(Event event) {
    System.out.println(PRICE_LOAD_EVENT + " received by listener " + this.getClass());
    try {
     TimeUnit.SECONDS.sleep(10);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }

  });

  // Event dispatcher
  while (true) {
   System.out.println("Event fired " + PRICE_LOAD_EVENT + ".............");
   EventHub.instance().fire(new Event(PRICE_LOAD_EVENT));

   try {
    TimeUnit.SECONDS.sleep(5);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }

   System.out.println("Event fired " + SECURITY_LOAD_EVENT + ".............");
   EventHub.instance().fire(new Event(SECURITY_LOAD_EVENT));

  }
 }

}


Finally, the output if you run the above class, which runs for ever in a while loop.

Event fired PL_EVENT.............
PL_EVENT received by listener class com.writtentest14.EventHubMain$1
PL_EVENT received by listener class com.writtentest14.EventHubMain$3
Event fired SL_EVENT.............
SL_EVENT received by listener class com.writtentest14.EventHubMain$2
Event fired PL_EVENT.............
PL_EVENT received by listener class com.writtentest14.EventHubMain$1


In the next post, I will integrate MBean components with MBean server to manage the EventHub via a JMX client like jconsole.

Labels: ,

May 28, 2014

Top 17 Java Coding Tips for job interviews and pre-interview coding tests

Tip #1: If you are asked to write a function or code, make sure that your code fails fast. Check for pre-conditions and post conditions. For, example, if you are writing a function to "apply given interest rate to given balance"

Pre-condition: Balance is a positive number and greater than zero. Interest rate is not a percentage and can't be > 1.
Post-condition: new balance is a positive number by applying the interest rate.

 
public BigDecimal updateBalance(BigDecimal balance, BigDecimal rate) {
//pre-condition check if(balance == null || rate == null) { throw new IllegalArgumentException("balance or interestRate cannot be null"); } if(!isGretaerThanZero(balance)) { throw new IllegalArgumentException("balance must be a +ve number > zero "); } if(isInputPercentage(rate) || !isGretaerThanZero(rate)){ throw new IllegalArgumentException("rate is not valid"); } BigDecimal newBalance = balance.multiply(BigDecimal.ONE.add(rate)); //postcondition checks -- wrong calculation if(!isGretaerThanZero(balance)) { throw new CalculationException("balance must be a +ve number > zero."); } if(newBalance.compareTo(balance) <= 0){ throw new CalculationException("new balance cannot be less or same as old balance "); } return newBalance;  
}
 
boolean isGretaerThanZero(BigDecimal input){
  return input.compareTo(BigDecimal.ZERO) > 0 ;
}
 
 
boolean isInputPercentage(BigDecimal input){
  return input.compareTo(BigDecimal.ONE) > 0 ;
}


Tip #2: Don't write big functions, and divide them into smaller meaningful functions as shown above with isGreaterThanZero, isInputPercentage, etc.  Favor meaningful function names as opposed to cluttering your code with comments. The function names must be self explanatory as to what you are doing.


Tip #3: Write JUnit tests to test your function or code. Test for both the positive and negative scenarios. You need junit-xxx.jar for the example below.

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

public class BalanceCalcTest {
  
 BalanceCalc calc;

 @Before
 public void init() {
  calc = new BalanceCalc();
 }
 
 @Test
 public void testUpdateBalance() {
  BigDecimal updatedBalance = 
    calc.updateBalance(new BigDecimal("100.00"), (new BigDecimal("0.10")));
  Assert.assertTrue(new BigDecimal("110.0").compareTo(updatedBalance) == 0);
 }
 
 
 @Test(expected = java.lang.IllegalArgumentException.class)
 public void negativeTestUpdateBalance() {
  BigDecimal updatedBalance = 
       calc.updateBalance(new BigDecimal("-100.00"), (new BigDecimal("0.10")));
  
 }
}


Tip #4If you are asked to write iterative version of function then you may be drilled  to write recursive version or vice-versa. When writing loops, don't use i or j as index variables. Use meaningful names. Also avoid nested loops where possible.

Reverse a given string input : iteration

public static String reverse(String input) {
        StringBuilder strBuilder = new StringBuilder();
        char[] strChars = input.toCharArray();

        for (int charIndex = strChars.length - 1; charIndex >= 0; charIndex--) {
            strBuilder.append(strChars[charIndex]);
        }

        return strBuilder.toString();
}

Reverse a given string input : recursion

public static String reverseRecursion(String input) {

        //exit condition. otherwise endless loop
        if (input.length() < 2) {
            return input;
       }

       return reverseRecursion(input.substring(1)) + input.charAt(0);

}

Note: You may be quizzed on tail recursion

Tip #5:  Familiarize yourself with order of complexity with the Big O notation to answer any follow up question like -- What is the order of complexity of the above function you wrote?


Tip #6: Code to interface. Initialize your collection with appropriate capacity. Don't return a null collection, instead return an empty collection like  Collections.<String>emptyList( );.

Don't do:

   HashMap<String, String> keyValues = new HashMap()<String, String>();
   ArrayList<String>  myList = new ArrayList<String>();

Do:


   Map<String, String> keyValues = new HashMap()<String, String>(20);
   List<String>  myList = new ArrayList<String>(100);

Tip #7: Favor composition over interface

Tip #8: Use generics where required. Recursion with Generics tutorial. Understanding generics with scenarios.

Tip #9: Reduce the accessibility, and make your objects immutable where appropriate. For example, a custom key class that is used to store objects in a map. How to make a Java class immutable tutorial.

Tip #10: Don't forget to override Object class's methods that are meant to be overridden like equals(...), hashCode( ), and toString( ).



Tip #11: When you have large if/else or switch statements, see if the Open/Closed design principle can be applied.

Tip #12: Don't assume that your objects and classes are going to be accessed by a single-thread. Safeguard your objects and classes against multi-threading. Java multi-threading questions and answers.

Tip #13: Use the right data types. For example, use either BigDecimal to represent monetary values in dollars and cents or long to represent them in their lowest units as just cents (400 cents for $4.0). Beware of max and minimum values for data types. If you want values larger than long, use BigInteger, which has no theoretical limit. The BigInteger class allocates as much memory as it needs to hold all the bits of data it is asked to hold

byte (-128 to 127) -->  short (2 bytes,  -32,768 to 32,767) --> char(2 bytes, 65,535) --> int (4 bytes, -2^31 to 2^31-1) --> long(8 bytes,  -2^63 to 2^63-1) --> float (4 bytes) --> double (8 bytes). boolean (true or false)

Also, never compare floating point variables to exact amount like

double amount = 12.05;
if(amount == 12.05) { //don't
    //...do something
}


Tip #14: Handle and propagate exceptions properly. Have a consistent usage of checked and unchecked exceptions.


Exception is swept under the carpet.

try {
   //do something
}
catch(Exception ex){
    //do nothing
}


CustomCheckedException is never reached as exceptions are polymorphic in nature. CustomCheckedException must be declared first above Exception.

try {
   //do something
}
catch(Exception ex){
    //do something
}

catch(CustomCheckedException ex){
    //do nothing
}


Tip #15: Write pseudo code for more difficult coding questions. At times drawing diagrams help you solve the solving problem.


Tip #16: Keep in mind some of the design principles like  SOLID design principles, Don't Repeat Yourself (DRY), and Keep It Simple ans Stupid (KISS). Also, think about the OO concepts -- A PIE.   Abstraction, Polymorphism, Inheritance, and Encapsulation. These principles and concepts are all about accomplishing

  • Low coupling: Coupling in software development is defined as the degree to which a module, class, or other construct, is tied directly to others. You can reduce coupling by defining intermediate components (e.g. a factory class or an IoC container like Spring) and interfaces between two pieces of a system. Favoring composition over inheritance can also reduce coupling. 
  • High cohesion: Cohesion is the extent to which two or more parts of a system are related and how they work together to create something more valuable than the individual parts. You don't want a single class to perform all the functions (or concerns) like being a domain object, data access object, validator, and a service class with business logic. To create a more cohesive system from the higher and lower level perspectives, you need to break out the various needs into separate classes.  


Tip #17: If you are coding in front of the interviewer, think out loud. It is not always possible to solve problems in an interview when you are nervous, but how you will go about solving a coding problem is equally important even if you don't solve it. So, let the interviewer know that you know how to approach a problem. Solve the problem first, and then find ways to optimize it in terms of performance and memory allocation.


Practice!, practice!!, practice!!!....Write  code!!, more code!!!, more code!!!!.  That is the only way. Any more tips or corrections folks?

Labels:

May 27, 2014

Understanding Open/Closed Principle (OCP) from the SOLID OO principles with a simple Java example

Spring Interview Questions and Answers Q1 - Q14 are FAQs

Q1 - Q4 Overview & DIP Q5 - Q8 DI & IoC Q9 - Q10 Bean Scopes Q11 Packages Q12 Principle OCP Q14 AOP and interceptors
Q15 - Q16 Hibernate & Transaction Manager Q17 - Q20 Hibernate & JNDI Q21 - Q22 read properties Q23 - Q24 JMS & JNDI Q25 JDBC Q26 Spring MVC Q27 - Spring MVC Resolvers

Q. Is there anything wrong with the following class design? If yes, can the design be improved?

package com.ocp;

import javax.management.RuntimeErrorException;

import org.apache.commons.lang.StringUtils;

public class MathOperation {
 
 public int operate(int input1, int input2, String operator){
  
  if(StringUtils.isEmpty(operator)){
   throw new IllegalArgumentException("Invalid operator: " + operator);
  }
  
  if(operator.equalsIgnoreCase("+")){
   return input1 + input2;
  }
  else if(operator.equalsIgnoreCase("*")){
   return input1 * input2; 
  } else {
   throw new RuntimeException("unsupported operator: " + operator);
  }
 }

}

JUnit test class.

package com.ocp;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

public class MathOperationTest {
 
 MathOperation operation;
 
 @Before
 public void init(){
  operation = new MathOperation();
 }
 
 @Test
 public void testAddition() {
  Assert.assertEquals(8, operation.operate(5, 3, "+"));
 }
 
 @Test
 public void testMultiplication() {
  Assert.assertEquals(15, operation.operate(5, 3, "*"));
 }

}

A. It’s not a good idea to try to anticipate changes in requirements ahead of time, but you should focus on writing code that is well written enough so that it’s easy to change. This means, you should strive to write code that doesn't have to be changed every time the requirements change. This is what the Open/Closed principle is. According to GoF design pattern authors "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". Spring framework promotes this principle.

In the above example, you can anticipate more operators like "-" (subtraction) and division (/) to be supported in the future and the class "MathOperation" is not closed for modification. When you need to support operators "-" and "%" you need to add 2 more "else if" statements. Whenever you see large if/else or switch statements, you need to think if "Open/Closed" design principle is more suited.


Let's open for extension and close for modifications

In the rewritten example below, the classes AddOperation and MultiplyOperation are closed for modificationbut open for extension by allowing you to add new classes like SubtractOperation and DivisionOperation by implementing the Operation interface.


Define the interface Operation.

package com.ocp;

public interface Operation {
       abstract int operate(int input1, int input2);
}


Define the implementations

package com.ocp;


public class AddOperation implements Operation {

 @Override
 public int operate(int input1, int input2) {
  return input1 + input2;
 }
 
}

package com.ocp;

public class MultiplyOperation implements Operation {

 @Override
 public int operate(int input1, int input2) {
  return input1 * input2;
 }
 
}


Finally, the JUnit test class

package com.ocp;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

public class MathOperation2Test {
 
 Operation operation;
  
 @Test
 public void testAddition() {
  operation = new AddOperation();
  Assert.assertEquals(8, operation.operate(5, 3));
 }
 
 @Test
 public void testMultiplication() {
  operation = new MultiplyOperation();
  Assert.assertEquals(15, operation.operate(5, 3));
 }

}


This is only a trivial example, but in real life applications, wherever you have large if/else statements, you need to think if OCP can be applied. Spring framework promotes this principle.


Q. Can you explain if the following classes are badly designed? 

Labels: ,

Learning to write functional programming with Java 8 with examples -- part 2

In the last post I created custom functional interfaces to explain functional programming, closure, and lambda expressions in Java 8. This post gives Java 8 API examples using lambda expressions and functional programming.

Example 1: The java.lang.Runnable interface has been made a functional interface.


package com.java8.examples;

public class Example1 {
 
 public static void main(String[] args) {
   System.out.println("main thread: " + Thread.currentThread().getName());
   
   //run method takes no arguments so: () -> (body)
   //closure worker thread1
   Runnable r = () -> (System.out.println("worker thread: " + Thread.currentThread().getName())); 
   new Thread(r).start(); //pass the Runnable closure to Thread constructor
   
   //closure worker thread2
   new Thread( () -> (System.out.println("worker thread: " + Thread.currentThread().getName()))).start(); 
 }
}


Output:

main thread: main
worker thread: Thread-0
worker thread: Thread-1


Example 2: The java.util.function package has a number of functional interfaces.

package com.java8.examples;

import java.util.function.Consumer;

public class Example2 {
 
  public static void main(String[] args) {
   //closure of Consumer 1. the accept(T t) method takes Integer here
   Consumer<Integer>  c1 = (x) -> {System.out.println("consumed: " + x);};
   //closure of Consumer 2. x is an Integer  
   Consumer<Integer>  c2 = (x) -> {System.out.println("consumed: " + x*x);};

   
   c1.accept(5);
   c2.accept(5);
   
   //andThen is a default method implementation in Consumer interface
   Consumer<Integer> c3 = c1.andThen(c2);
   c3.accept(6);
 }
}

Output:

consumed: 5
consumed: 25
consumed: 6
consumed: 36


Example 3: The Function&ltT, R> is similar to Consumer<T>, but the Function interface has a return value in its apply(T t) method, whereas the Consumer  has a void method accept(T t).

package com.java8.examples;

import java.util.function.Function;

public class Example3 {
 
  public static void main(String[] args) {
   //closure of Function.  apply(T t) method takes Double here
   Function<Double, Double>  c1 = (arg) -> (arg + arg);
   Function<Double, Double>  c2 = (arg) -> (arg * arg);
  
   Double result1 = c1.apply(5.0);
   Double result2 = c2.apply(5.0);
   
   System.out.println("result1= " + result1);
   System.out.println("result2= " + result2);
   
   //andThen is a default method implementation in Function interface
   Function<Double, Double> c3 = c1.andThen(c2);
   Double result3 = c3.apply(6.0);
   
   System.out.println("result3= " + result3);// 6 + 6 = 12, 12 * 12 = 144;
   
 }
}


Output:

result1= 10.0
result2= 25.0
result3= 144.0


Example 4: The Predicate<T> interface from java.util.function package has test(T t) method that returns a boolean value indicating test condition has passed or failed. The predicates are often used to  filter a collection of objects.

package com.java8.examples;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Example4 {
 
 private static final int SHORT_NAME_LENGTH = 3;
 
 public static void main(String[] args) {
  
  List<String> languages = Arrays.asList("Java", "C++", "PHP", "C#", "Scala", "JRuby", "Jython");
  
  //The Predicate interface has test(T t) that returns a boolean
  Predicate<String> shortNamePredicate = (s) -> (s.length() <= SHORT_NAME_LENGTH); // closure
  
 
  Predicate<String> startsWithCPredicate = (s) -> (s.startsWith("J")); //closure
  
  languages.stream()
           .filter(shortNamePredicate)
           .forEach(e -> System.out.println("short names: " + e));
  
  languages.stream()
           .filter(startsWithCPredicate)
           .forEach(e -> System.out.println("starts with J: " + e));
   
 }
}


Output:

short names: C++
short names: PHP
short names: C#
starts with J: Java
starts with J: JRuby
starts with J: Jython


There are more examples relating working with Java collection -> Understanding Java 8 Streams and working with collections using Lambda expressions

Labels: ,

May 26, 2014

Learning to write functional programming with Java 8 with examples -- part 1

In the earlier post entitled  Understanding Java 8 Lambda expressions with working examples -- part 1, we looked at Summable example to illustrate functional programming. In this tutorial, I will go in more detail with similar examples with scenarios. The example is a a simple arithmetic operation.

Scenario 1:  The Operate interface with the annotation @FunctionalInterface. This annotation ensures that you can only have a single abstract method. You can have additional default and static method implementations.

Step 1: Define the interface. It is an abstract method by default, and  @FunctionalInterface ensures that you can only define a Single Abstract Method (aka SAM).


package com.java8.examples;

@FunctionalInterface
public interface Operation {
    int operate(int operand1, int operand2); 
}

Step 2: The OperationTest class that uses the functional interface with lambda expressions like (x, y) -> (x + y); and  (x, y) -> (x * y) to add and multiply respectively. The method name operate(int operand1, int operand2) is not explictly called as the compiler knows to work it out from the parameters passed int operand1, int operand2 which method to invoke.

package com.java8.examples;

public class OperationTest {

 public static void main(String[] args) {
   OperationTest test = new OperationTest();
   System.out.println("add result = " + test.add(2, 3));
   System.out.println("multiply result = " + test.multiply(2, 3));
 }

 public int add( int input1,  int input2) {
   Operation adder = (x, y) -> (x + y);
   return adder.operate(input1, input2);
 }  
 
 public int multiply( int input1,  int input2) {
   Operation multiplier = (x, y) -> (x * y);
   return multiplier.operate(input1, input2);
 }  
}

Output:

add result = 5
multiply result = 6

The above example will give the same output even without the @FunctionalInterface annotation. You could even have "abstract" in front of  int operate(int operand1, int operand2);

package com.java8.examples;

public interface Operation {
 abstract int operate(int operand1, int operand2);
}



Scenario 2: Have another Operation2 interface that takes 3 integer parameters.


package com.java8.examples;

public interface Operation2 {
 abstract int operate(int operand1, int operand2, int operand3); 
}


The OperationTest class that uses both interfaces. The Operation that take 2 integer parameters and Operation2 that takes 3 integer parameters.

package com.java8.examples;

public class OperationTest {

 public static void main(String[] args) {
   OperationTest test = new OperationTest();
   System.out.println("add result = " + test.add(2, 3));
   System.out.println("multiply result = " + test.multiply(2, 3));
   System.out.println("add 3 numbers result = " + test.add2(2, 3, 4));
 }

 public int add( int input1,  int input2) {
   Operation adder = (x, y)  -> (x + y);
   return adder.operate(input1, input2);
 }  
 
 
 public int multiply( int input1,  int input2) {
   Operation subtracter =  (x, y) -> (x * y);
   return subtracter.operate(input1, input2);
 } 
 
 public int add2( int input1,  int input2, int input3) {
   Operation2 adder = (x, y, z)  -> (x + y + z);
   return adder.operate(input1, input2, input3);
 }  
 
}


Output:

add result = 5
multiply result = 6
add 3 numbers result = 9



Scenario 3: Why do you have default methods in Java 8 interfaces?

This example demonstrates that default methods provide default behaviors, and closures are used to have  special behaviors like add, multiply, divide, subtract, print, etc.

Step 1: Here is the revised Operation interface with default methods.

package com.java8.examples;

import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.Objects;

@FunctionalInterface
public interface Operation<Intetger>  {
 
    //SAM -- Single Abstract Method.
    //identifier abstract is optional
    Integer operate(Integer operand);
 
    default Operation<Integer> add(Integer o){
       return (o1) -> operate(o1) +   o;
    }
 
    default Operation<Integer> multiply(Integer o){
      return (o1) -> operate(o1) * o;
    }
 
    //define other default methods for divide, subtract, etc
 
    default Integer getResult() {
    return operate(0);
    }
    
 default void print(){
  System.out.println("result is = " + getResult());
 }
   
}





Step 2: The revised OperationTest class.

package com.java8.examples;

import static java.lang.System.out;

public class OperationTest {
 
 public static void main(String[] args) {
 
  Operation<Integer> calc = (x) -> (2);
  
  Operation complexOp = calc.add(3)
         .multiply(4)
         .multiply(2)
         .multiply(2)
         .add(4);
  
  complexOp.print();
 
  int result = complexOp.getResult();
 } 
 
}




Output:

result is = 84


We know that Java does not support multiple implementation inheritance to solve the diamond problem (till Java 8). Java did only support multiple interface inheritance. That is, a class can implement multiple interfaces. By having default method implementations in interfaces, you can now have multiple behavioral inheritance in Java 8.  Partially solving the diamond problem.


Scenario 4: Why do you have static methods in Java 8 interfaces?

The static methods are helper methods. Prior to Java 8, the Java APIs used to have separate interfaces and utility methods. For example, Collection interface and Collections utility class, Path interface and Paths utility class, etc.

So, instead of doing Collections.sort(list, ordering), in Java 8 APIs you could do list.sort(ordering);

Secondly, static helper methods are more expressive with meaningful names like plus5, plus10, etc as shown below.

package com.java8.examples;

import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.Objects;

@FunctionalInterface
public interface Operation<Intetger>  {
 
 //SAM -- Single Abstract Method.
 //identifier abstract is optional
 Integer operate(Integer operand);
 
    default Operation<Integer> add(Integer o){
       return (o1) -> operate(o1) +   o;
    }
 
    default Operation<Integer> multiply(Integer o){
      return (o1) -> operate(o1) * o;
    }
 
    //define other default methods for divide, subtract, etc
 
    default Integer getResult() {
    return operate(0);
    }
    
 default void print(){
  System.out.println("result is = " + getResult());
 }
   
 
 //ads 5 to a given number
 static Integer plus5(Integer input) {
  return input + 5 ;
 }
}


Now, how to invoke the static method via Lambda expressions:

package com.java8.examples;

import static java.lang.System.out;

public class OperationTest {
 
 public static void main(String[] args) {
 
  //plus5 is an expressive static helper method that adds 5 to a given number
  Operation<Integer> calc = (x) -> Operation.plus5(2);
  
  Operation complexOp = calc.add(3)
         .multiply(4)
         .multiply(2)
         .multiply(2)
         .add(4);
  
  complexOp.print();
 
  int result = complexOp.getResult();
  
 } 
}


Output:

result is = 164


Learning to write functional programming with Java 8 with examples -- part 2

Labels: ,

May 25, 2014

Auditing database record changes in Oracle

Extends Database interview questions - triggers using Sybase database

Q. What are some of the considerations in auditing database table data?
A.
  • Creating audit tables without any constraints to store record changes.  Audit tables are heavily hit with inserts, hence needs to have fewer indices if at all required.
  • Decide on what combination of triggers are required like  Create, Update, or Delete in the CRUD operations.
  • Create the triggers.

Here is an example for a given table shown below


CREATE TABLE bus_rule(
    id                           NUMBER(30)     NOT NULL,
    code                         VARCHAR2(50)   NOT NULL,
    rule_entry_id                NUMBER(30)     NOT NULL,
    name                         VARCHAR2(100)  NOT NULL,
    effective                    date           NULL,
    expires                      date           NULL,
    created_by                   VARCHAR2(30)   NOT NULL,
    created_date                 TIMESTAMP      NOT NULL,
    updated_by                   VARCHAR2(30)   NOT NULL,
    updated_date                 TIMESTAMP      NOT NULL,
    CONSTRAINT bus_rule_pk PRIMARY KEY (id),
    CONSTRAINT fk_bus_rule_rule_entry_id FOREIGN KEY (rule_entry_id) REFERENCES bus_rule_entry(id)
);


Step 1: Create a corresponding audit table to store historical data. Note that this table does not have any constraints as it is historical table. It adds a new column called "crud_operation" to tag if the data stored was due to Create, Update or Delete.

CREATE TABLE bus_rule_audit(
 id                           NUMBER(30)     NOT NULL,
    code                         VARCHAR2(50)   NOT NULL,
    rule_entry_id                NUMBER(30)     NOT NULL,
    name                         VARCHAR2(100)  NOT NULL,
    effective                    date           NULL,
    expires                      date           NULL,
    created_by                   VARCHAR2(30)   NOT NULL,
    created_date                 TIMESTAMP      NOT NULL,
    updated_by                   VARCHAR2(30)   NOT NULL,
    updated_date                 TIMESTAMP      NOT NULL,
    crud_operation               char(1)   NOT NULL
);


Step 2: Create triggers in Oracle

CREATE OR REPLACE TRIGGER bus_rule_trig

AFTER INSERT OR UPDATE OR DELETE 
ON bus_rule

REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
  DECLARE
    crud_operation  CHAR(1);
 
  BEGIN
             
  IF INSERTING THEN
     crud_operation := 'C';
  ELSIF UPDATING THEN
     crud_operation := 'U';
  ELSIF DELETING THEN
     crud_operation := 'D';
 END IF;
        

 IF INSERTING OR UPDATING THEN
 
      INSERT INTO bus_rule_audit (ID,CODE,RULE_ENTRY_ID,NAME,EFFECTIVE,EXPIRES,CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,CRUD_OPERATION) 
        VALUES (:NEW.ID, :NEW.CODE,:NEW.RULE_ENTRY_ID,:NEW.NAME,:NEW.EFFECTIVE,:NEW.EXPIRES,:NEW.CREATED_BY,:NEW.CREATED_DATE,:NEW.UPDATED_BY,:NEW.UPDATED_DATE,  crud_operation);

    ELSE 
      
      INSERT INTO bus_rule_audit (ID,CODE,RULE_ENTRY_ID,NAME,EFFECTIVE,EXPIRES,CREATED_BY,CREATED_DATE,UPDATED_BY,UPDATED_DATE,CRUD_OPERATION) 
        VALUES (:OLD.ID, :OLD.CODE,:OLD.RULE_ENTRY_ID,:OLD.NAME,:OLD.EFFECTIVE,:OLD.EXPIRES,:OLD.CREATED_BY,:OLD.CREATED_DATE,:OLD.UPDATED_BY,:OLD.UPDATED_DATE,  crud_operation);
    
    END IF;  
       
END;


Now, if you perform any CUD operation table bus_rule the bus_rule_trig will fire to insert records into the audit table bus_rule_audit.


Q. Why do you need to be careful as to where you use triggers?
A. The main problems with triggers are

a) they are global - they apply no matter what the context of the table activity; and
b) they are candid; it's easy to forget they are there until they hurt you with unintended consequences.


You may also like:

Labels: ,

May 24, 2014

Core Java Coding Questions: Creating a custom hierarchical List in Java -- Part 3

Q. Can you write a custom list class that supports following features?

1. Allows you to maintain a parent/child hierachy of sub lists.
2. Allows you to create sublists from a given list and a predicate (i.e a condition)
3. If you add an item or element to a list, the addition must be propagated to its parent and child lists.
4. If you remove an element from a list, the removal must be propagated to its parent and child lists.

In the previous parts
In this part, you will be adding an add(...) method to add an item to the hierarchical list.


Step 1: Remove the UnsupportedOperationException with the following recursive method call. Recursion is used to add to the parent and children.

//....removed methods

public class CustomList<E> implements List<E> {

    //...removed constructors & methos  

 @Override
 public boolean add(E e) {
  return add(e, null);
 }
 
 protected boolean add(E e, CustomList<E> givenList) {

  // check if the predicate (i.e. condition) is met
  if (!evaluate(e)) {
   return false;
  }

  boolean hasAdded = true;

  // if parent exists, add to the parent
  if (parent != null && parent != givenList) {
   // Recursive method call. The parent takes care of siblings...
   hasAdded = parent.add(e, this);
  }

  // if addition fails, return false
  if (!hasAdded) {
   return false;
  }

  //add it to the actual list
  hasAdded = this.list.add(e);

  if (!hasAdded) {
   if (parent != null) {
    throw new IllegalStateException("Failed to add !!");
   } else {
    return false;
   }
  }

  // Add to the sublists
  for (CustomList<E> sublist : sublists) {
   if (sublist != givenList) {
    // recursive method call
    sublist.add(e, this);
   }
  }

  return true;
 }

 private boolean evaluate(E e) {
  return (this.predicate != null) ? this.predicate.evaluate(e) : true;
 }
 
 
 //...removed some methods 
}





Step 2: The CustomListTest that adds items to the CustomList. Note that the initial list creation was slightly modified to make "initialList" mutable, so that new items can be added.

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CustomListTest {

 public static void main(String[] args) {
  /**
   * Arrays.asList returns a List wrapper around an array. This wrapper
   * has a fixed size and is directly backed by the array, and as such
   * calls to set will modify the array, and any other method that
   * modifies the list will throw an UnsupportedOperationException.
   * hence creating a new ArrayList(...) instance
   */
  List<Integer> initialList = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

  CustomList<Integer> customList = new CustomList<Integer>(initialList);
  System.out.println("customList: " + customList);

  Predicate<Integer> oddNumberPredicate = new OddNumberPredicate<Integer>();
  CustomList<Integer> oddNumbersSubList = customList.subList(oddNumberPredicate);
  System.out.println("oddNumbersSubList: " + oddNumbersSubList);

  Predicate<Integer> factorOf5Predicate = new FactorOf5Predicate<Integer>();
  CustomList<Integer> factorOf5SubList = customList.subList(factorOf5Predicate);
  System.out.println("factorOf5SubList: " + factorOf5SubList);

  Predicate<Integer> factorOf3Predicate = new FactorOf3Predicate<Integer>();
  CustomList<Integer> factorOf3SubList = oddNumbersSubList.subList(factorOf3Predicate);
  System.out.println("factorOf3SubList : " + factorOf3SubList);

  System.out.println("Demonstrate printing customList again");
  System.out.println("customList : " + customList);

  // add an item or element
  customList.add(11); // this should be added to customList and
       // oddNumbersSubList
  customList.add(15); // this should be added to all four lists.

  System.out.println("After adding 11 & 15: ");
  System.out.println("customList : " + customList);
 }
}

The output is:

customList: list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

oddNumbersSubList: parent: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list: [1, 3, 5, 7, 9]

factorOf5SubList: parent: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list: [5, 10]

factorOf3SubList : parent: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
parent: [1, 3, 5, 7, 9]
list: [3, 9]

Demonstrate printing customList again
customList : list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
child: [1, 3, 5, 7, 9]
child: [5, 10]
child: [3, 9]

After adding 11 & 15: 
customList : list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15]
child: [1, 3, 5, 7, 9, 11, 15]
child: [5, 10, 15]
child: [3, 9, 15]

Labels:

May 23, 2014

Recursion Vs Tail Recursion Java example to reversing a given string

Reversing a given string input is a popular Java interview question. Let's look at reversing a String with recursion and tail recursion. If you want to better understand recursion with a diagram, read Java coding questions frequently asked in technical tests and job interviews -- iteration Vs recursion.

Input: Peter
Output: reteP

Recursion

public static String reverseRecursion(String input) {

        //exit condition. otherwise endless loop
        if (input.length() < 2) {
            return input;
        }

        return reverseRecursion(input.substring(1)) + input.charAt(0);
}

The processing happens as shown below

reverseRecursion("Peter")
reverseRecursion("eter") + 'P'
(reverseRecursion("ter") + 'e') + 'P'
((reverseRecursion("er") + t) + 'e') + 'P'
(((reverseRecursion("r") + e) + t) + 'e') + 'P'
((("r" + 'e') + 't') + 'e') + 'P'
(("re" + 't') + 'e' ) + 'P'
("ret" + 'e') + 'P'
"rete" + 'P'
"reteP"


Tail Recursion


public static String reverseTailRecursion(String input, String output ) {

        if (input.length() == 0) {
            return output;
        }

        return reverseTailRecursion(input.substring(1), input.charAt(0) + output);
}


The processing happens as shown below

reverseTailRecursion("Peter", "")
reverseTailRecursion("eter", "P")
reverseTailRecursion("ter", "eP")
reverseTailRecursion("er", "teP")
reverseTailRecursion("r", "eteP")
reverseTailRecursion("", "reteP")
"reteP"



Why use tail recursion?

In tail recursion the last call in the recursion is a call to the function and there is nothing left to do when the recursive call returns. This means in tail recursion the compilerdrop the growing stack, hence less likely to run out of stack space.

Labels:

Why favor composition over inheritance in Java OOP?

This is a very popular job interview question, and the correct answer depends on the problem you are trying to solve. You need to ask the right questions before deciding one over the other.

Q. How do you express an ‘is a’ relationship and a ‘has a’ relationship or explain inheritance and composition?
A. The ‘is a’ relationship is expressed with inheritance and ‘has a’ relationship is expressed with composition. Both inheritance and composition allow you to place sub-objects inside your new class. Two of the main techniques for code reuse are class inheritance and object composition.


Inheritance is uni-directional. For example House is a Building. But Building is not a House. Inheritance uses extends key word. Composition: is used when House has a Bathroom. It is incorrect to say House is a Bathroom. Composition simply means using instance variables that refer to other objects. The class House will have an instance variable, which refers to a Bathroom object.

Q. Which one to favor, composition or inheritance?
A. The guide is that inheritance should be only used when subclass ‘is a’ super class. Don’t use inheritance just to get code reuse. If there is no ‘is a’ relationship then use composition for code reuse.

Reason #1: Overuse of implementation inheritance (uses the “extends” key word) can break all the subclasses, if the super class is modified. Do not use inheritance just to get polymorphism. If there is no ‘is a’ relationship and all you want is polymorphism then use interface inheritance with composition, which gives you code reuse.

Reason #2: Composition is more flexible as it happens at run time whereas inheritance happens at compile-time.

Reason #3: Composition offers better testability than Inheritance. Composition is easier to test because inheritance tends to create very coupled classes that are more fragile (i.e. fragile parent class) and harder to test in isolation. The IoC containers like Spring, make testing even easier through injecting the composed objects via constructor or setter injection.


Q. Can you give an example of the Java API that favors composition?
A. The Java IO classes that use composition to construct different combinations using the decorator design pattern at run time.

//construct a reader
StringReader sr = new StringReader(“Some Text....”);
//decorate the reader for performance
BufferedReader br = new BufferedReader(sr);
//decorate again to obtain line numbers
LineNumberReader lnr = new LineNumberReader(br);

The GoF design patterns like strategy, decorator, and proxy favor composition for code reuse over inheritance.

Q. Can you a give an example where GoF design patterns use inheritance?
A. A typical example for using inheritance is in frameworks where the template method design pattern is used.

Another common pattern that would use inheritance is Composite pattern.


Q. What questions do you ask yourself to choose composition (i.e. has-a relationship) for code reuse over implementation inheritance (i.e. is-a relationship)? 

A. Do my subclasses only change the implementation and not the meaning or internal intent of the base class? Is every object of type House really “is-an” object of type Building? Have I checked this for “Liskov Substitution Principle

According to Liskov substitution principle (LSP), a Square is not a Rectangle provided they are mutable. Mathematically a square is a rectangle, but behaviorally a rectangle needs to have both length and width, whereas a square only needs a width.

Another typical example would be, an Account class having a method called calculateInterest(..). You can derive two subclasses named SavingsAccount and ChequeAccount that reuse the super class method. But you cannot have another class called a MortgageAccount to subclass the above Account class. This will break the  Liskov substitution principle because the intent is different. The savings and cheque accounts calculate the interest due to the customer, but the mortgage or home loan accounts calculate the interest due to the bank

Violation of LSP results in all kinds of mess like failing unit tests, unexpected or strange behavior, and violation of open closed principle (OCP) as you end up having if-else or switch statements to resolve the correct subclass. For example,

if(shape instanceof Square){
     //....
} 
else if (shape instanceof Rectangle){
    //...
}

If you cannot truthfully answer yes to the above questions, then favor using “has-a” relationship (i.e. composition). Don't use “is-a” relationship for just convenience. If you try to force an “is-a” relationship, your code may become inflexible, post-conditions and invariants may become weaker or violated, your code may behave unexpectedly, and the API may become very confusing. LSP is the reason it is hard to create deep class hierarchies.

Always ask yourself, can this be modeled with a “has-a” relationship to make it more flexible?

For example, If you want to model a circus dog, will it be better to model it with “is a” relationship as in a CircusDog “is a” Dog or model it as a role that a dog plays? If you implement it with implementation inheritance, you will end up with sub classes like CircusDog, DomesticDog, GuideDog, SnifferDog, and StrayDog. In future, if the dogs are differentiated by locality like local, national, international, etc, you may have another level of hierarchy like LocalCircusDog, NationalCicusDog, InternationalCircusDog, etc extending the class CircusDog. So you may end up having 1 animal x 1 dog x 5 roles x 3 localities = 15 dog related classes. If you were to have similar differentiation for cats, you will end up having similar cat hierarchy like WildCat, DomesticCat, LocalWildCat, NationalWildCat, etc. This will make your classes strongly coupled.


If you implement it with interface inheritance, and composition for code reuse, you can think of circus dog as a role that a dog plays. These roles provide an abstraction to be used with any other animals like cat, horse, donkey, etc, and not just dogs. The role becomes a “has a” relationship. There will be an attribute of interface type Role defined in the Dog class as a composition that can take on different subtypes (using interface inheritance) such as CircusRole, DomesticRole, GuideRole, SnifferRole, and StrayRole at runtime. The locality can also be modeled similar to the role as a composition. This will enable different combinations of roles and localities to be constructed at runtime with 1 dog + 5 roles + 3 localities = 9 classes and 3 interfaces (i.e. Animal, Role and Locality). As the number of roles, localities, and types of animals increases, the gap widens between the two approaches. You will get a better abstraction with looser coupling with this approach as composition is dynamic and takes place at run time compared to implementation inheritance, which is static.


Extracted from Core Java Career Essentials, which has more examples, code, and design topics.

Labels: ,

May 22, 2014

Can you list best 5 software books you consider must read books, and why those made it into your top 5 list?

A. Great books are that you read many times and constantly refer to.  From the books you list, an interviewer can judge your experience and attitude towards software development. Open ended questions like this can reveal a lot about an interview candidate.

[My list]

1. Effective Java - by Joushua Bloch.  This book gives you a deeper understanding of the Java programming language so that you can write code that is clearer and more correct. The author teaches how to write good Java code like


  • minimizing accessibility of classes and members.
  • favoring immutability.
  • favoring composition over inheritance for code reuse.
  • favoring interfaces over abstract classes.
  • minimizing the scope of local variables.
  • avoiding float and double if exact answers are required.
  • proper exception handling.


to name a few.


2. Enterprise Integration Patterns by Gregor Hohpe. Enterprise integration is too complex and very vital in building distributed applications. Patterns can provide guidance by documenting tried and tested experience to avoid pitfalls and apply the best practices. This pattern catalog describes 65 integration patterns. Many ESB or SOA platforms already implement some of the patterns described in this book because the vendor recognized the recurring problem and incorporated the solution right into the package.  It starts describing various integration styles like File Transfer, Shared Database, Remote Procedure Invocation, and then the most parts of the book is about messaging. This is a comprehensive cookbook of solutions to common integration patterns.


3. Code Complete by Steve McConnel. This book is a bible of best practices and will inform and stimulate your thinking—and help you write good quality code. This book is widely considered as one of the best practical guides to programming. For example,


  • Meaningful variable names for nested loops instead of just i's, j's, and k's.
  • Variable naming conventions, creating short names, standardizing prefixes, and names to avoid.
  • Data types fundamentals and common mistakes.
  • Software craftsmanship with self-documenting code, coding techniques, and code layout.
  • Programming tools to write quality code
  • Code tuning technics in logics, loops, expressions, iterations, and routines.
  • Code refactoring, testing, and debugging  techniques.
  • ...and much more



4. Design Patterns: Elements of Reusable Object-Oriented Software by the Gang of Four -- Ralph Johnson, John Vlissides, Richard Helm, and Erich Gamma. This book captures a wealth of experience about the design of object-oriented software. The 23 design patterns described in the book allow designers to create more flexible, elegant, and ultimately reusable designs without having to rediscover the design solutions. Goes well hand-in-hand with the book Head First Design Patterns by Eric Freeman , Bert Bates , Kathy Sierra, and Elisabeth Robson.


5. Head First JavaScript by Michael Morrison and JavaScript: The Good Parts by Douglas Crockford -- If you enjoy web development, the trend is to build Rich Internet applications with JavaScript, HTML5, and CSS3. For example, AngularJS is a pupular JavaScript based MVW(i.e. Model View Whatever) framework to build web applications. Some even say that "JavaScript is the new Java". So, it is really good to get a good handle on JavaScript as it is quite different from Java, and takes time to really understand it. Don't be fooled by the fact that JavaScript has the term "Java" in it. That is probably the only similarity between the two languages.


Many of the other stuff can be continuously learned by subscribing to quality online sites like (infoq.com, javalobby.com, etc), blogs and articles. Good developers do have a list of go to sites for APIs, reference documentation, and quality blog posts.


What are your best 5 reads on software development?

Labels:

Java 8 Optional class to alleviate some of the pains of unsightly null pointer checks and defensive coding

The most prevalent runtime exception (aka unchecked) exception in Java is the NullPointerException. You need to code defensively to avoid NullPointerException as shown below. Later, we will see how the class java.util.Optional that was introduced in Java 8 will alleviate this problem to some extent.

Pre Java 8 without the java.util.Optional class


public class Person {

 private String name;
 private int age;
 
 private HealthInsurance insurance; 
 
 //getters and setter
}


public class HealthInsurance {

 private String name;
 private Extra[] extras;

 //getters and setters
}


public class Extra {
      
 private String name;

 //getters and setters 
}


Now, here is the main class that invokes printExtras(Person person), where you need to check for null

public class PersonTest {

 public static void main(String[] args) {

  Person person1 = new Person();
  person1.setName("John");
  printExtras(person1);
  
  Person person2 = new Person();
  person2.setName("Peter");
  
  HealthInsurance healthIns = new HealthInsurance();
  Extra[] healthExtras = { new Extra("Physio"), new Extra("Optical"), new Extra("Chiro") };
  healthIns.setExtras(healthExtras);
  
  person2.setInsurance(healthIns);
  printExtras(person2);

 }

 private static void printExtras(Person person) {
  if (person != null && 
   person.getInsurance() != null 
   && person.getInsurance().getExtras() != null) {
   
   Extra[] extras = person.getInsurance().getExtras();
   for (Extra extra : extras) {
    System.out.println(extra.getName());
   }
  }

 }
}


In Java 8 with java.util.Optional class


Take note of the Optional class.
package com.java8.examples;

import java.util.Optional;

public class Person {
 
 private String name;
 private int age;
 private Optional<HealthInsurance> insurance = Optional.empty(); //default
 
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getAge() {
  return age;
 }
 
 public void setAge(int age) {
  this.age = age;
 }
 
 
 public Optional<HealthInsurance> getInsurance() {
  return insurance;
 }
 public void setInsurance(Optional<HealthInsurance> insurance) {
  this.insurance = insurance;
 }
}


package com.java8.examples;

import java.util.Optional;

public class  HealthInsurance{

 private String name;
 private Optional<Extra[]> extras = Optional.empty(); //default

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Optional<Extra[]> getExtras() {
  return extras;
 }

 public void setExtras(Optional<Extra[]> extras) {
  this.extras = extras;
 }
}


package com.java8.examples;

public class Extra {

 private String name;

 public Extra(String name) {
  super();
  this.name = name;
 }

 public String getName() {
  return name;
 }
}


Finally, the main class that make use of the Optional.of methods, and the printExtras(Optional person) is much simpler with functional programming and lambda expressions.


package com.java8.examples;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

public class PersonTest {

 public static void main(String[] args) {

  Person person1 = new Person();
  person1.setName("John");

  Optional<Person> p1 = Optional.of(person1);
  printExtras(p1);

  Person person2 = new Person();
  person2.setName("Peter");

  // health ins and extras are supplied
  HealthInsurance healthIns = new HealthInsurance();
  Extra[] healthExtras = { new Extra("Physio"), new Extra("Optical"), new Extra("Chiro") };

  healthIns.setExtras(Optional.of(healthExtras));
  person2.setInsurance(Optional.of(healthIns));

  Optional<Person> p2 = Optional.of(person2);
  printExtras(p2);

 }

 private static void printExtras(Optional<Person> person) {
  person
      .flatMap(Person::getInsurance)
      .flatMap(HealthInsurance::getExtras)
      .ifPresent((p) -> {for(int i = 0; i < p.length; i++) {
                        System.out.println(p[i].getName());
                }
                        });
         
     }
}


Both approaches outputs

Physio
Optical
Chiro


Here are the convenient methods that the Optional class support

  • ifPresent( ):  returns true if a value is present in the optional.
  • get( ):  returns a reference to the item contained in the optional object, if present, otherwise throws a NoSuchElementException.
  • ifPresent(Consumer<T>consumer):  passes the optional value, if present, to the provided Consumer (lambda expression or method reference).
  • orElse(T other): returns the value, if present, otherwise returns the value in other.
  • orElseGet(Supplier<T> other):  returns the value if present, otherwise returns the value provided by the Supplier (lambda expression or method reference).
  • orElseThrow(Supplier<T> exceptionSupplier): returns the value if present, otherwise throws the exception provided by the Supplier (lambda expression or method reference)

Note:  In Java you cannot simply get rid of the null references that have historically existed, but before Java 8, you need to rely on your code and proper documentation to understand if a reference is optional. java.util.Optional<T> class has been added to deal with optional object references. The intention with the Optional class is not to replace every null-able reference, but to help in the creation of more robust APIs you could tell if  you can expect an optional reference by reading the signature of a method.

Labels: , ,

May 21, 2014

7 useful miscellaneous additions you must know in Java 8

The much awaited addition in Java 8 are Lambda expressions to be used in functional programming and default and static methods in interfaces to support multiple behavior inheritance and helper methods. Here are a few other additional handy additions in Java 8.

Addition #1: String.join( ) method, which is an opposite of String.split(...) was there from pre Java 8.

Example 1:

String[] javaTechnologies = {"Java", "JEE", "JDBC", "Spring"};
String joined = String.join(",", javaTechnologies); //Java,JEE,JDBC,Spring

Example 2:

 String joined = String.join("/", "var", "opt", "oracle"); // var/opt/oracle

Addition #2: The Comparator interfaces have a number of useful methods to sort objects with options to nest multiple fields with thenComparing(...), and other handy methods like nullsFirst( ), nullsLast( ), naturalOrder( ), reverseOrder( ), etc. This was made possible as Java 8 interfaces can have default methods (which gives you multiple behavior inheritance) and static methods (a replacement for helper classes).

Example 1:

Arrays.sort(people, Comparator.comparing(Person::getName)  
                               .thenComparing(Person::getAge) ;
  
Example 2:

Comparator<Person> multiFieldComparator = 
    Comparator.comparing(Person::getGender, Comparator.nullsFirst(Comparator.naturalOrder()))
              .thenComparing(Person::getName, Comparator.nullsLast(Comparator.naturalOrder()))
              .thenComparing(Person::getAge,  Comparator.nullsLast(Comparator.reverseOrder())) ;
     
//parallel() processing using Fork/Join 
List<Object> sortedPeople = people.stream().parallel().sorted(multiFieldComparator).collect(Collectors.toList());   


Addition #3: In Java you cannot simply get rid of the null references that have historically existed, but before Java 8, you need to rely on your code and proper documentation to understand if a reference is optional (i.e can be null) as shown below,

import java.util.ArrayList;
import java.util.List;

public class PersonTest {

 public static void main(String[] args) {

  List<Person> people = new ArrayList<>();
  people.add(new Person("John", 35, Person.Gender.MALE));
  people.add(new Person("Simone", 30, Person.Gender.FEMALE));
  people.add(new Person("Shawn", 30, Person.Gender.MALE));
  
  Person foundPerson = find("Sam", people); 
  System.out.println(foundPerson.getName()); //NullPointerException
  
 }

 public static Person find(String name, List<Person> Persons) {
  for (Person person : Persons) {
   if (person.getName().equalsIgnoreCase(name)) {
    return person;
   }
  }
  return null;
 }
}




In Java 8java.util.Optional<T> class has been added to deal with optional object references. The intention with the Optional class is not to replace every null-able reference, but to help in the creation of more robust APIs you could tell if  you can expect an optional reference by reading the signature of a method.

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class PersonTest {

 public static void main(String[] args) {

  List<Person> people = new ArrayList<>();
  people.add(new Person("John", 35, Person.Gender.MALE));
  people.add(new Person("Simone", 30, Person.Gender.FEMALE));
  people.add(new Person("Shawn", 30, Person.Gender.MALE));

  Optional<Person> foundPerson = find("Sam", people);
  System.out.println(foundPerson.orElse(new Person("Sam", 35, Person.Gender.MALE))); 
  
 }

 public static Optional<Person> find(String name, List<Person> Persons) {
  for (Person Person : Persons) {
   if (Person.getName().equals(name)) {
    return Optional.of(Person);
   }
  }
  return Optional.empty();
 }
}


The find method signature tells you that it returns a person optionally.

Addition #4: In cases where you want to detect result overflow errors in int and long, the methods addExact, subtractExact, multiplyExact, and toIntExact in Java 8, the java.lang.Math class throws an ArithmeticException when the results overflow. Generally, it is recommended to use BigInteger if you expect large values.

public class DataOverflowTest {
 
 public static void main(String[] args) {
  
  //for int -2^31 and a maximum value of 2^31-1, which is -2147483648 to 2147483647
  
  int i = 2147483647 + 1;
  System.out.println(i); //wrong -- prints -2147483648 due to data overflow 
  
  //Java 8
  Math.addExact(2147483647, 1);  //java.lang.ArithmeticException: integer overflow
 }
}


Addition #5: The ability to lazily read lines from a file with Files.lines(...). For example, let's read technologies.txt that has

Java
JEE
JDBC
Hibernate
Spring

Now the code that covers previous additions as well.

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.stream.CloseableStream;

public class FileReadTest {
 
 public static void main(String[] args) {
  Path path = Paths.get("c:\\temp\\technologies.txt");
  try(CloseableStream<String> lines = Files.lines(path, Charset.forName("UTF-8"))){
   Optional<String> found = lines.filter(p -> p.contains("Spring")).findFirst();
   System.out.println(found.orElse("NOT FOUND!!"));
  } catch (IOException e) {
   e.printStackTrace();
  }//CloseableStream is AutoCloseable 
 }
}


Addition #6: The @Repeatable annotation.

Pre Java 8:

public @interface Habit {
 String value();
}

public @interface Habits {
     Habit[] value();
}

@Habits({@Habit("habit1"), @Habit("habit2")})
public class Person  {
   //......
}


Post Java 8:

import java.lang.annotation.Repeatable;

@Repeatable(Habits.class)
public @interface Habit {
 String value();
}


@Habit("habit1")
@Habit("habit2")
public class Person  {
   //...
}

In Pre Java 8, if you repeat the same annotation, you will get a compile-time error "Duplicate annotation". In Java 8, you can repeat the same annotation with the @Repeatable annotation.


Addition #7: Java 8 introduces the "Type Annotations", which are annotations that can be placed anywhere you use a type.


  • new operator, 
  • type casts, 
  • implements clauses and 
  • throws clauses. 

Handy for stronger type checking, but can clutter your code. Use them judiciously. For example,

@NotNull String str1 = ...
@Email String str2 = ...
Map.@NonNull Entry = ...
new @NonEmpty List<String>(notEmptySet)
List<@ReadOnly @Localized Message> messages = ...

Labels: ,