Google

Jul 27, 2012

JavaScript common mistakes and tools

If you are writing Java Script code, it is worth using code quality tools like JSLint and JSHint  to avoid any pitfalls like

  • using global variables
  • leaving trailing commas in object declarations
  • not understanding the difference between closures and functions
  • forgetting to declare a var
  • naming a variable with the same name as an HTML id, etc.

It is also essential to use JavaScript testing frameworks like Jasmine, Selenium + WebDriver, QUnit, and TestSwarm. QUnit is an easy-to-use, JavaScript test suite that was developed by the jQuery project to test its code and plugins, but is capable of testing any generic JavaScript code. One of the challenges of JavaScript rich application is testing it for cross  browser compatibility. The primary goal of TestSwarm is to simplify the complicated, and time-consuming process of running JavaScript test suites in multiple browsers. It provides all the tools necessary for creating a continuous integration work-flow for your JavaScript rich application. Debugging JavaScripts can be a painful part of web development. There are handy browser plugins, built-ins and external tools to make your life easier. Here are a few such tools.

  • Cross-browser (Firebug Lite, JS Shell, Fiddler, Blackbird Javascript Debug helper, NitobiBug, DOM Inspector (aka DOMi), Wireshark / Ethereal)
  • Firefox (JavaScript Console, Firebug, Venkman, DOM Inspector, Web Developer Extension, Tamper Data, Fasterfox, etc)
  • Internet Explorer (JavaScript Console, Microsoft Windows Script Debugger, Microsoft Script Editor, Visual Web Developer, Developer Toolbar, JScript Profiler, JavaScript Memory Leak Detector)
  • Opera (JavaScript Console, Developer Console, DOM Snapshot, etc)
  • Safari ("Debug" menu, JavaScript Console, Drosera - Webkit, etc)
  • Google Chrome (JavaScript Console and Developer Tools)

Q. What are the common JavaScript errors or bad practices that you have noticed
A.

1. Not using the var to declare your variables. If you don't use "var", your variable will become global. Your code will work with global variables, but it can create strange errors that are harder to debug and fix. It is also imperative to define proper namespaces and declare variables within the scope of that namespace.


Here is an example of global window scope and a neatly packaged "name" variable and "greet" function into an object literal. You can also note that the value of 'this' is changed to the containing object, which is no longer the global "window" object. This is quite useful as you can keep a set of variables and functions abstracted into one namespace without any potential conflicts of names.

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>


<script type="text/javascript">

    //bad - global variable and function

    window.name= "window-global-scope";   //global scope

    var greet = function(greeting) {
     console.log(greeting + " " + this.name);
   }

   //good: encapsulated variable and function
   object = {
        name: "object-scope",
        
     greet: function(greeting) {
      console.log(greeting + " " + this.name);
        }
    }


</script>

</head>
<body onload="greet('hello');object.greet('howdy')">

</body>
</html>


Note: It is a best practice to define your HTML and Javascript in separate files. The above code snippet is for illustration purpose only.

The output will be

hello window-global-scope
howdy object-scope


2. Not understanding the difference between "==" operator and "===" operator. 
  • ==  operator compare the values but it doesn’t compare the data type of operands. 
  • === operator in JavaScript compare not only the value of operands, but also the data type. If the data type of operands is different, it will always return false.
3. Not de-referencing a variable once it has been used. Setting a variable to null once it has been used will allow the garbage collector of the js engine to reclaim that object. 

4. Not understanding the difference between innerText and innerHTML. The innerHTML gets the html code inside the element and innerText gets the text inside the element. So, if you had <p> Some text </p> the innerText will only return "Some text" without the element <p>, and innerHTML will return  <p> Some text </p>  

5.  Not understanding what the implicit scope "this" refers to. For example,


function  Account(balance) {
 this.balance = balance;
 this.getTenPercentOfbalance = function() {
      return balance * 0.10;
 };
}


var mortgageAccount = new Account(10000.00);
mortgageAccount.getTenPercentOfbalance(); // returns 1000.00


Now, if you try

var tenPercentMethod = mortgageAccount.getTenPercentOfbalance();
tenPercentMethod();  // throws an error


Why did it throw an error?

The implicit "this" points to the global Window object, and the Window object does not have the function getTenPercentOfbalance( ).

The above two lines can be written with the JavaScript head object 'window' as shown below.

  var window.tenPercentMethod = window.mortgageAccount.getTenPercentOfbalance();
  window.tenPercentMethod();  // throws an error


Important: The value of this, passed to all functions, is based on the context in which the function is called at runtime.

You can fix this by

tenPercentMethod.apply(mortgageAccount); // now it uses this == mortgageAccount


When invoking constructors with the 'new' keyword, 'this' refers to the “object that is to be” when the constructor function is invoked using the new keyword. Had we not used the new keyword above, the value of this would be the context in which Account is invoked — in this case the 'window' head object.

var mortgageAccount =  Account(10000.00); // without new key word. this is passed to the constructor as 'window'.  
console.log(mortgageAccount.balance); // undefined, the value is actually set at window.balance


'this' in nested functions

You might be wondering what happens to 'this' when it is used inside of a function that is contained inside of another function. The bad news is in ECMA 3, this loses its way and refers to the head object (window object in browsers), instead of the object within which the function is defined. The good news is that this will be fixed in ECMAScript 5.

Here is another example on this reference and scope: In JavaScript, scope is resolved during execution of functions. If you have nested functions, once you have executed a function nested within a function, JavaScript has lost your scope and is defaulting to the best thing it can get, window (i.e. global). To get your scope back, JavaScript offers you two useful functions, call and apply.


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>


<script type="text/javascript">
   object = {
        name: "object-scope",
        
     greet: function() {
      nestedGreet =  function(greeting) {
           console.log(greeting + " " + this.name);
            }
   
      
      //scope is resolved during execution of functions
            nestedGreet('hello');                 //hello window-global-scope
                                                  //loses its scope and defaults to window
            nestedGreet.call(this, 'hello');      //hello object-scope 
            nestedGreet.apply(this, ['hello']);   //hello object-scope
            
     }
   }


</script>

</head>
<body onload="object.greet()">

</body>
</html>


6. Not understanding getting the function back versus invoking the function, especially when used in callback functions. The callback functions are not invoked directly. They are iether invoked asynchronously after a certain event like button click or after a certain timeout.

function sayHello(){
    return "Hello caller";
}


Now, if you do the following, you only get the function back.

var  varFunction = sayHello;  // stores the function to the variable varFunction
setTimeout(sayHello, 1000)    // can also pass it to other functions. 
                              // This is a callback function  
                              // Will call sayHello a second later.

window.load = sayHello;       // Can attach to objects. Will call sayHello when the page loads 
                              // This is a callback function 



But if you add '( )' to it as shown below, you will be actually invoking the function.

sayHello();    //invoke the function
varFunction(); //invoke the function


So, the addition of paranthese to the right invokes the function. So, incorrectly assigning like shown below will callback the function immediately.

Wrong:

setTimeout(sayHello(), 1000); // won't wait for a second 

<input id="mybutton" onclick="sayHello();return false;" type="button" value="clickMe" /> //invokes it straight a way without waiting for onclick event.


Correct:

setTimeout(sayHello, 1000); // waits for a second
//jQuery to the rescue
$('#mybutton').click(function(){
    return  "Hello caller";
})

So, it is a best practice to favor using proven JavaScript frameworks to avoid potential pitfalls.


7. Not understanding JavaScript scopes. Javascript only has global and function scopes, and does not have block scopes as in other languages like Java. In JavaScript, functions are values that can be assigned to a variable, including arrays. In the example below, the above correct code fragment uses a powerful feature of Javascript known as first order functions. In every iteration the variable item is declared that contains the current element from the array. The function that is generated on the fly contains a reference to "item" and will therefore be part of its closure. Logically, this means that in the first function captures the value  {'id': 'fname', 'help': 'Entr your first name'}, and the second function captures the value {'id': 'lname', 'help': 'Enter your surname'}, and so on. The incorrect function is also showed to understand the difference.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>

<script type="text/javascript">
   
    function showHelp(help) {
   document.getElementById('help').innerHTML = help;
 }
 
 function initializeHelpWrongly() {
   var helpText = [
       {'id': 'fname', 'help': 'Entr your first name'},
       {'id': 'lname', 'help': 'Enter your surname'} 
     ];

    
   for (var i = 0; i < helpText.length; i++) {
     var item = helpText[i];
  //Wrong: by the time this function is executed the for loop would have been completed
  //and the value of the item would be the last item in the array, which is id: lname
     document.getElementById(item.id).onfocus = function() {
      console.log(item.help);
      showHelp(item.help)  
  }
   }
 }

 function initializeHelpCorrectly() {
   var helpText = [
       {'id': 'fname', 'help': 'Entr your first name'},
       {'id': 'lname', 'help': 'Enter your surname'} 
     ];

   for (var i = 0; i < helpText.length; i++) {
     var item = helpText[i];
  //In every iteration a new function is created on the fly, which contains 
  //a reference to current item being processed in the loop
  //and will therefore be part of its closure. Logically, this means that in the 
  //first function captures id: fname, and second function captures id:lname so on.
     document.getElementById(item.id).onfocus = function(item) {
       return function() {
        console.log(item.help);
        showHelp(item.help)   
       };  
     }(item);
   }
 }
 
</script>

</head>

<!-- try substituting initializeHelpWrongly()-->
<body onload="initializeHelpCorrectly();">

<p id="help">Help text appear here</p>  
<p>fname: <input type="text" id="fname" name="fname"></p>  
<p>lname: <input type="text" id="lname" name="lname"></p> 


</body>
</html>




8. Not testing the  JavaScript code for cross browser compatibility.


9. Trying to reinvent the wheel by writing substandard functions as opposed to reusing functions from proven frameworks and libraries.


Q. What tips would you give to someone requiring to perform computation intensive task using JavaScript?
A. Computation intensive JavaScript tasks, for example, in a loop can make a browser unresponsive. Here are some tips to consider.

1. Try and optimize the loop so that it completes within say 150 ~ 200 milli seconds. Anything over this value can affect the user experience.

2. Redesign the functionality by offloading the processing to a back end server.

3. The HTML 5 supports Web Worker and it brings multithreading to JavaScript. Prior to Web Worker,  developers  were creating asynchronous processing by using techniques like setTimeout(), setInterval(), XMLHttpRequest, and event handlers. The Web Workers specification defines an API for spawning background scripts in your web application. Web Workers allow you to do things like fire up long-running scripts to handle computationally intensive tasks, but without blocking the UI or other scripts to handle user interactions. 

4. If you are not on HTML 5 yet, put a wait inside the body of the loop so as to let the browser breath. Don't use sleep(5); Instead use setTimeout(..) function, which uses the non-blocking I/O paradigm. 

for (var i = 0, len = items.length; i < len; i++){
    setTimeout(function(){
        processItem(items[i])
    }, 5)  
}

Note: The above code can be further improved with a queue, dynamic batch sizes, and eliminating the need for a for loop.

Labels:

Jul 24, 2012

SQL Interview Questions and Answers: storing a tree structure in a database table



Q. How will you represent a hierarchical structure shown below in a relational database? or How will you store a tree data structure into DB tables?



A.The hierarchical  data is an example of the composite design pattern. The entity relationship diagrams (aka ER diagram) are used to represent logical and physical relationships between the database tables. The diagram below shows how the table can be designed to store tree data by maintaining the adjacency information via superior_emp_id.



as you can see the "superior_emp_id" is a foreign key that points to the emp_id in the same table. So, Peter has null as he has no superiors. John and Amanda points to  Peter who is their manager or superior and so on.

The above table can be created using SQL DDL (Data Definition Language) as shown below.


CREATE TABLE employee (

emp_id          NUMBER (4) CONSTRAINT emp_pk PRIMARY KEY,
emp_name        VARCHAR2 (40) NOT NULL, 
title           VARCHAR2 (40),   
dept_id         NUMBER (2) NOT NULL,
superior_emp_id NUMBER (4) CONSTRAINT emp_fk REFERENCES employee(emp_id)

CONSTRAINT emp_pk
PRIMARY KEY NONCLUSTERED (emp_id)

)


This can be represented as an object model  to map relational data as shown below


public class Employee {

   private Long id;
   private String name;
   private String title;
   private Employee superior;
   private Set subordinates;

   //getters and setters are omitted

}


Q. How will you find out the superior for an emplyee?
A. You can use a self-join to find the manager of an employee

Select e.emp_id,e.emp_name, title from
employee e, employee s
where e.superior_emp_id = s.employee_id
  and e.emp_id = 3

This should return

1, Peter, cio 


Q. Is there any other way to to store tree structure in a relational database?
A. Yes, it can be done using the "modified preorder tree traversal" as described below.






As shown in the diagram above, each node is marked with a left and right numbers using a modified preorder traversal as shown above. This can be represented in a database table as shown below.



As you can see the numbers indicate the relationship between each node. All left values greater than 6 and right values less than 11 are descendants of  6-11 (i.e Id: 3 Amanda). Now if you want to extract out the 2-6 sub-tree for Amanda you can write the SQL as follows

SELECT * FROM employee WHERE left_val BETWEEN 6 and 11 ORDER BY left_val ASC;

Which will return Amanda, Ralph, and Jeanne.

If you want to get ancestors to a given node say 7-8 Ralph, you can write the SQL as follows

SELECT * FROM employee WHERE left_val < 7 and right_val > 8 WHERE ORDER BY left_val ASC;


Which will return: Peter and Amanda.

If you want to find out the number of descendants for a node, all you need is the left_val and right_val of the node for which you want to find the  descendants  count. The formula is

No. of descendants = (right_val - left_val -1) /2

So,  for 6 -11 Amanda, (11 - 6 - 1) /2 =  2 descendants
       for 1-12  Peter, (12 - 1 -1 ) / 2 = 5 descendants.
       for 3-4   Mary, (4 -3 - 1) / 2 =  0, means it is a child and has no descendants.

The modified preorder traversal is a little more complicated to understand, but is very useful.

You may also like:

Labels:

Jul 19, 2012

UML diagrams interview questions and answers


Q: What are the different types of UML diagrams?
A:

Use case diagrams


Depicts the typical interaction between external users (i.e. actors) and the system. The emphasis is on what a system does rather than how it does it. A use case is a summary of scenarios for a single task or goal. An actor is responsible for initiating a task. The connection between actor and use case is a communication association.



Capturing use cases is one of the primary tasks of the elaboration phase of RUP. In its simplest usage, you capture a use case by talking to your users and discussing the various things they might want to do with the system.

When to use ‘use case’ diagrams?

  • Determining user requirements. New use cases often generate new requirements.
  • Communicating with clients. The simplicity of the diagram makes use case diagrams a good way for designers and developers to communicate with clients.
  • Generating test cases. Each scenario for the use case may suggest a suite of test cases.






Class diagrams

Class diagram technique is vital within Object Oriented methods. Class diagrams describe the types of objects in the system and the various static relationships among them. Class diagrams also show the attributes and the methods. Class diagrams have the following possible relationships:

Association: A relationship between instances of 2 classes.

Aggregation: An association in which one class belongs to a collection (does not always have to be a collection. You can also have cardinality of “1”). This is a part of a whole relationship where the part can exist without the whole. For example: A line item is whole and the products are the parts. If a line item is deleted then the products need not be deleted.

Composition: An association in which one class belongs to a collection (does not always have to be a collection. You can also have cardinality of “1”). This is a part of a whole relationship where the part cannot exist without the whole. If the whole is deleted then the parts are deleted. For example: An Order is a whole and the line items are the parts. If an order is deleted then all the line items should be deleted as well (i.e. cascade deletes).

Generalization: An inheritance link indicating that one class is a superclass of the other. The Generalization expresses the “is a” relationship whereas the association, aggregation and composition express the “has a” relationship.

Realization: Implementation of an interface.

Dependency: A dependency is a weak relationship where one class requires another class. The dependency expresses the “uses” relationship. For example: A domain model class uses a utility class like Formatter etc.


When to use class diagrams?  

  • Class diagrams are the backbone of Object Oriented methods. So they are used frequently. 
  • Class diagrams can have a conceptual perspective and an implementation perspective. During the analysis draw the conceptual model and during implementation draw the implementation model. 

Package diagrams

To simplify complex class diagrams you can group classes into packages.



When to use package diagrams?

  • Package diagrams are vital for large projects.

Object diagrams

Object diagrams show instances instead of classes. They are useful for explaining some complicated objects in detail about their recursive relationships etc.



When to use object diagrams?
  • Object diagrams are a vital for large projects.
  • They are useful for explaining structural relationships in detail for complex objects.

Sequence diagrams

Sequence diagrams are interaction diagrams which detail what messages are sent and when. The sequence diagrams are organized according to time. The time progresses as you move from top to bottom of the diagram. The objects involved in the diagram are shown from left to right according to when they take part.





Collaboration diagrams

Collaboration diagrams are also interaction diagrams. Collaboration diagrams convey the same message as the sequence diagrams. But the collaboration diagrams focus on the object roles instead of the times at which the messages are sent. 

The collaboration diagrams use the decimal sequence numbers as shown in the diagram below to make it clear which operation is calling which other operation, although it can be harder to see the overall sequence. The top-level message is numbered 1. The messages at the same level have the same decimal prefix but different suffixes of 1, 2 etc according to when they occur. 


When to use an interaction diagrams?

When you want to look at behavior of several objects within a single use case. If you want to look at a single object across multiple use cases then use statechart diagram as described below.


State chart diagrams

Objects have behavior and state. The state of an object depends on its current activity or condition. This diagram shows the possible states of the object and the transitions that cause a change in its state.



When to use a state chart diagram?

Statechart diagrams are good at describing the behavior of an object across several use cases. But they are not good at describing the interaction or collaboration between many objects. Use interaction and/or activity diagrams in conjunction with a statechart diagram.

Use it only for classes that have complex state changes and behavior. For example: the User Interface (UI) control objects, Objects shared by multi-threaded programs etc.


Activity diagram

This is really a fancy flow chart. The activity diagram and statechart diagrams are related in a sense that statechart diagram focuses on object undergoing a transition process and an activity diagram focuses on the flow of activities involved in a single transition process.




In domain modeling it is imperative that the diagram conveys which object (or class) is responsible for each activity. Activity diagrams can be divided into object swimlanes that determine which object is responsible for which activity. The swimlanes are quite useful because they combine the activity diagram’s depiction of logic with the interaction diagram’s depiction of responsibility. A single transition comes out of each activity, connecting to the next activity. A transition may join or fork. 

When to use activity diagrams? 

The activity and statechart diagrams are generally useful to express complex operations. The great strength of activity diagrams is that they support and encourage parallel behavior. The activity and statechart diagrams are beneficial for workflow modeling with multi-threaded programming.

Component and Deployment diagrams

A component is a code module. Component diagrams are physical diagrams analogous to a class diagram. The deployment diagrams show the physical configuration of software and hardware components. The physical hardware is made up of nodes. Each component belongs to a node.






Labels:

Jul 17, 2012

Java coding question on the popular Fibonacci sequence

The Fibonacci sequence is 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, and 89 on to infinity is popular with the interviewers. The sequence has a series of interesting properties. The sum of any two consecutive numbers equals the next highest number. After the first four numbers, the ratio of any number to its next highest number approaches 0.618. The ratio of alternate numbers approach .382. These ratios are often simplified to the key Fibonacci levels 38%, 50%, and 62% and used in stock trading analysis, growth in living things like reproduction of rabbits, arrangement of leaves in a plant, scales of pineapples, etc. So, why is this asked in programming interview questions? This is to see if you can think logically and write code. Here are a few questions on this Fibonacci sequence.

The Fibonacci numbers under 2000 are : 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597.

Where the zeroth number being 0, first number being 1, second number being 1 (i.e. 0+1), third number being 2 (i.e. 1+1), fourth number being 3 (i.e. 1+2) and so on till the 17th number being 1597 (i.e 610 + 987).

Q. Can you write a function to determine the nth Fibonacci number?
A. This can be achieved with recursion or iteration. You can learn more about recursion at iteration Vs recursion. If you provide an iterative solution then there will be follow up question to write recursive solution and vice versa.

Recursive solution:

public class RecursiveFibonacci {
 
 public int fibonacci(int n){
  if(n<0){
    throw new IllegalArgumentException("Input parameter is invalid " + n); 
  }
  
  if(n == 0){
    return 0;
  }
  
  else if(n <= 2){
    return 1;
  }
  else {
    return fibonacci(n-1)+fibonacci(n-2); // head recursion
  } 
 }
 
 public static void main(String[] args) {
   int nThfibonacciNo = new RecursiveFibonacci().fibonacci(17);
   System.out.println(nThfibonacciNo);
 }

}


As per the above implementation

fibonacci(0) = 0;
fibonacci(1) = 1;
fibonacci(2) = 1;
fibonacci(3) = fibonacci(3-1) +  fibonacci(3-2) = fibonacci(2) +  fibonacci(1) = 1 + 1 = 2

The 5th  fibonacci number will be:

Recursion 1:  [ fibonacci(4) + fibonacci(3) ]
Recursions 2 and 3:  [ fibonacci(3)+ fibonacci(2) ] + [ fibonacci(2) + fibonacci(1) ]
Recursions 4, 5, 6, and 7: [ fibonacci(2) ] +  [ fibonacci(1) ] + [1] + [1] + [1]
Recursion 8 and 9: [1] + [1] + 1 + 1 + 1 = 5

Each recursion is shown with [ ].  So, the 5th fibonacci number is 5.

Iterative Solution:



public class IterativeFibonacci {

 public int fibonacci(int n) {
  if (n < 0) {
   throw new IllegalArgumentException("Input parameter is invalid " + n);
  }

  int num1 = 0, num2 = 1;
  
  //zeroth fibonacci number is 0
  if (n == 0)
   return 0;
  
  //first and second fibonacci numbers are 1 and 1
  if (n == 1 || n == 2)
   return 1;
  
  int current = num1 + num2;
  
  //compute from the third number onwards by adding the previous fibonacci number
  for (int i = 3; i <= n; i++) {
   num1 = num2;            
   num2 = current;            
   current = num1 + num2;
  }
  
  return current;
 }

 public static void main(String[] args) {
  int nThfibonacciNo = new IterativeFibonacci().fibonacci(17);
  System.out.println(nThfibonacciNo);
 }

}




The output is: 1597

Diagrams can often simplify things and gives better clarity.




Q. How will you compute the sum of all even Fibonacci numbers under 2000?
A. This is a bit of a twist to evaluate your ability to construct the logic

public class TwistedFibonacci {

 public static void main(String args[]) {
  int num1, num2, current, evenSum;
  num1 = 0;
  num2 = 1;
  current = num1 + num2;
  evenSum = 0;

  while (current + num2 < 2000) {
   num1 = num2;
   num2 = current;
   current = num1 + num2;
   
   if (current % 2 == 0) { // if the remainder is zero then even number
    if (current > 0) {
     System.out.println(current);
    }

    evenSum += current;
   }
  }

  System.out.println("Sum of the even Fibonacci numbers  under 2000: " + evenSum);
 }
}



The output is:


2
8
34
144
610
Sum of the even Fibonacci numbers  under 2000: 798


Unit tests are not shown, but in actual interviews, you must show unit tests as well.

Labels: ,

Jul 11, 2012

Can you write Java code by asking the right questions?

Core Java Coding Questions and Answers for beginner to intermediate level

Q1 Q2 Q3 Q4 Q5 Q6




Q. How will you go about writing code for counting the number of repeated words in the order of decreasing count for a given text input?

For example, input text = "The third-rate mind is only happy when it is thinking with the majority. The second-rate mind is only happy when it is thinking with the minority. The first-rate mind is only happy when it is thinking."

A. As mentioned before, the interviewer is not expecting you to come up with the perfect solution. He/she will be more interested in finding out the following:

1. Can you write pseudo code?
2. Do you analyze the requirements properly by asking the right questions?
3. Can you write basic code by referring to the Java API, etc?
4. Do you write unit tests?

Let's look at these in more etail.

1.Can you write pseudo code?
  • tokenize the input text into words
  • build a map<word, count> to store the individual words and its relevant count
  • iterate through the tokenized words and if the word is already stored, increment its count and if not already stored, store it with the count of 1.
  • sort the map by count in decrementing order
  • loop through the sorted map and print the "word" and its count.

2.Do you analyze the requirements properly by asking the right questions?
  • How are the words tokenized? by whitespace character only, white space and punctuations, how about URLs? , etc, The regular expression can be used for splitting the text. [ignore URL to keep it simple]
  • Are there any common words that need to be ignored? For example, 'the', 'a', 'or', 'and', etc. [yes]
  • Is it case sensitive? Should word and WORD be treated as the same word? [yes]

3.Can you write basic code by referring to the Java API, etc?
  • Use regex to split string into tokens
  • Use a Map that has o(1) look up to save the tokens and increment the count
  • Use a custom comparator to sort the map by its count in descending order. This means most repeated words at the top.




Here is the sample code --  DuplicateCounter

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public final class DuplicateCounter {

 private static final String REGEX_TO_SPLIT_TEXT_BY_WHITESPACE_AND_PUNCTUATION = "([.,!?:;'\"-]|\\s)+";
 private static final String[] WORDS_TO_IGNORE = {"is", "the", "a", "or", "and"};  // keep it short for demo

 public Map<String, Integer> processGivenText(String text) {
  //pre-condition check
  if(text == null) {
   throw new IllegalArgumentException("The input text cannot be null ");
  }

  //split the text into words
  String[] tokenizedWords = text.split(REGEX_TO_SPLIT_TEXT_BY_WHITESPACE_AND_PUNCTUATION);
  
  Map<String, Integer> readWords = new HashMap<String, Integer>(100);
  
  for (String word : tokenizedWords) {
   word = word.toLowerCase(); // make it case insensitive
   
   //if one of the words to be ignored, move on to the next word
   if(Arrays.asList(WORDS_TO_IGNORE).contains(word)){
    continue;
   }
   
   if (readWords.containsKey(word)) {
    int count = readWords.get(word);
    readWords.put(word, count + 1); // store incremented count
   } else {
    readWords.put(word, 1);
   }
  }

  // return the sorted LinkedMap 
  return sortByValue(readWords);
  
 }
 
 
 /**
  * Sort the given map by its value i.e. count as opposed to key
  * @param unsortedMap
  * @return
  */
 private Map<String, Integer> sortByValue(Map<String, Integer> unsortedMap) {
      List<Map.Entry<String, Integer>> sortedKeyList = new LinkedList<Map.Entry<String, Integer>>(unsortedMap.entrySet());
   //anonymous inner class to sort using a Comparator
      Collections.sort(sortedKeyList, new Comparator<Map.Entry<String, Integer>>() {
   @Override
   public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2) {
    return -e1.getValue().compareTo(e2.getValue());
   }
       
      });

     //LinkedHashmap maintains the order in which the elements were added 
     Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>(unsortedMap.size());
     for (Entry<String, Integer> entry : sortedKeyList) {
      sortedMap.put(entry.getKey(), entry.getValue());
  }
  
     return sortedMap;
 } 
}



Note that sorting a map by its values as opposed to its key is a bit tricky and it is done via the sortByValue method shown above.

Here is the sample main method that makes use of the class DuplicateCounter
    public static void main(String[] args) {
  Map<String, Integer> sortedByCountWords = new DuplicateCounter()
    .processGivenText("The third-rate mind is only happy when it is thinking with the majority. The second-rate mind is only happy when it is thinking with the minority. The first-rate mind is only happy when it is thinking.");

  // print word and its counts
  for (Map.Entry<String, Integer> entry : sortedByCountWords.entrySet()) {
   System.out.format("word '%s' counted  %s  time(s) \n", entry.getKey(), entry.getValue());
  }
 }
 
The output will be something like
word 'when' counted  3  time(s) 
word 'only' counted  3  time(s) 
word 'thinking' counted  3  time(s) 
word 'rate' counted  3  time(s) 
word 'happy' counted  3  time(s) 
word 'mind' counted  3  time(s) 
word 'it' counted  3  time(s) 
word 'with' counted  2  time(s) 
word 'second' counted  1  time(s) 
word 'majority' counted  1  time(s) 
word 'third' counted  1  time(s) 
word 'minority' counted  1  time(s) 
word 'first' counted  1  time(s) 

4.Do you write unit tests?

It is imperative to write both positive and negative test cases to test  your functionality.


import java.util.Map;


import java.util.Map;
import junit.framework.Assert;
import org.junit.Test;


public class DuplicateCounterTest {
 
 private static final String INPUT_TEXT = "The third-rate mind is only happy when it is thinking with the majority." + 
                                          "The second-rate mind is only happy when it is thinking with the minority." + 
                                     "The first-rate mind is only happy when it is thinking.";
 
 private static final String  word1 = "third";
 private static final String  word2 = "rate";
 private static final String  word3 = "thinking";
 private static final String  word4 = "is";
 
 
 @Test
 public void testPositiveScenario() {
  DuplicateCounter dc = new DuplicateCounter();
  Map<String, Integer> sortedByCountWords = dc.processGivenText(INPUT_TEXT);
  
  Assert.assertTrue(sortedByCountWords.size() == 13);
  
  Assert.assertTrue(sortedByCountWords.get(word1) == 1);  
  Assert.assertTrue(sortedByCountWords.get(word2) == 3);
  Assert.assertTrue(sortedByCountWords.get(word3) == 3);
 }
 
 @Test
    public void testNegativeScenario() {
     DuplicateCounter dc = new DuplicateCounter();
  Map<String, Integer> sortedByCountWords = dc.processGivenText(INPUT_TEXT);
  
  Assert.assertNull(sortedByCountWords.get(word4)); 
 }

}

Coding questions can reveal a lot about a candidate and his/her ability to write code.

Labels:

Jul 10, 2012

XML interview questions and answers

Q. What is XML?
A. XML stands for eXtensible Markup Language. XML is a grammatical system for constructing custom markup languages for describing business data, mathematical data, chemical data etc. XML loosely couples disparate applications or systems utilizing JMS, Web services etc. XML uses the same building blocks that HTML does: elements, attributes and values.

Q. Why is XML important?
A.
  • Scalable: Since XML is not in a binary format you can create and edit files with anything and it’s also easy to debug. XML can be used to efficiently store small amounts of data like configuration files (web.xml, application.xml, struts-config.xml, etc) to large company wide data with the help of XML stored in the database as a CLOB.
  • Fast Access: XML documents benefit from their hierarchical structure. Hierarchical structures are generally faster to access because you can drill down to the section you are interested in.
  • Easy to identify and use: XML not only displays the data but also tells you what kind of data you have. The mark up tags identifies and groups the information so that different information can be identified by different application.
  • Stylability: XML is style-free and whenever different styles of output are required the same XML can be used with different style-sheets (XSL) to produce output in XHTML, PDF, TEXT, another XML format, etc.
  • Linkability, in-line usability, universally accepted standard with free/inexpensive tools.

Q. When would you not use an XML?
A. XML is verbose and it can be 4-6 times larger in size compared to a csv or a tab delimited file. If your network lacked bandwidth and/or your content is too large and network throughput is vital to the application then you may consider using a csv or tab delimited format instead of an XML. JSON might be another alternative.

Q. Which is better to store data as elements or as attributes?
A. A question arising in the mind of XML/DTD designers is whether to model and encode certain information using an element, or alternatively, using an attribute. The answer to the above question is not clear-cut. But the general guideline is:
  • Using an element: <book><title>Lord of the Rings</title>...</book>: If you consider the information in question to be part of the essential material that is being expressed or communicated in the XML, put it in an element
  • Using an attribute: <book title=" Lord of the Rings "/>: If you consider the information to be peripheral or incidental to the main communication, or purely intended to help applications process the main communication, use attributes.
The principle is data goes in elements and metadata goes in attributes.  Elements are also useful when they contain special characters like “<”, “>”, etc which are harder to use in attributes. The most important reason to use element is its extensibility. It is far easier to create child elements to reflect complex content than to break an attribute into pieces. You can use attributes along with elements to refine your understanding of that element with extra information. Attributes are less verbose but using attributes instead of child elements with the view of optimizing document size is a short term strategy, which can have long term consequences. If verbosity and performance are of utmost importance, then XML might be a wrong choice. There are alternatives like JSON, CSV, Tab delimited data, FIX (Financial Information eXchange), etc.

Q. What is a well-formed XML document?
A. A well formed document adheres to the following rules for writing an XML.
  • A root element is required. A root element is an element, which completely contains all the other elements.
  • Closing tags are required. <cust>abc</cust> or <cust/>
  • Elements must be properly nested.
  • XML is case sensitive. <CUSTOMER> and <Customer> elements are considered completely separate.
  • An attribute’s value must always be enclosed in either single or double quotes.
  • Entity references must be declared in a DTD before being used except for the 5 built-in (<, > etc) discussed in the previous question.
Q. What is a valid XML document?
A. For an XML document to be valid, it must conform to the rules of the corresponding DTD (Document Type Definition – internal or external) or XSD (XML Schema Definition).


Q. Why use an XML document as opposed to other types of documents like a text file etc?
A.
  • It is a universally accepted standard.
  • Free and easy to use tools are available. Also can be stored in a database.
  • Fast access due to its hierarchical structure.
  • Easy to identify and use due to its markup tags.

Q. What is your favorite XML framework or a tool?
A.  My favorite XML framework is JiBX, which unmarshals an XML document to graph of Java objects and marshals a graph of Java objects back to  an XML document. It is simple to use, very flexible and fast. It can be used with existing Java classes.


Q. Explain where your project needed XML documents?
A. It is hard to find a project, which does not use XML documents.

  • XML is used to communicate with disparate systems via messaging or Web Services.
  • XML based protocols and standards like SOAP, ebXML, WSDL etc are used in Web Services.
  • XML based deployment descriptors like web.xml, ejb-jar.xml, etc are used to configure the JEE containers. Having said this, with the advent of annotatiions, use of XML for wiring up artefacts has reduced.
  • XML based configuration files are used by open-source frameworks like Hibernate, Spring, Struts, and Tapestry etc.

Q. WHat is JSON (JavaScript Object Notation) and why do you need JSON when there is XML?
A. JSON is a new human readable data format that has become very popular in the last few years, especially in web development.

JSON is very similar to XML. They both try to solve the same problem by creating a simple, human readable format for storing data. JSON was designed with web in mind, so it works really well with JavaScript. The two key benefits of JSON over XML are:
  • Faster to parse
  • Takes up less space
Learn more about JSON with code.

XML format:

<user>
   <firstname>Peter</firstname>
   <surname>Smith</surname>
   <age>12</age>
</user>


JSON format:


{"user":{"firstname":"Peter","surname":"Smith","age":12}}
JSON is ideal for mobile and web applications.

Labels:

Jul 6, 2012

Java coding questions frequently asked in technical tests and job interviews -- part 4: iteration Vs recursion

Core Java Coding Questions and Answers for beginner to intermediate level

Q1 Q2 Q3 Q4 Q5 - Q8 Q9 Q10 Q11 Q12 - Q14 Q15

Q. Can you write a sample code that will count the number of "A"s in a given text? Show both iterative and recursive approaches?

A. Let's assume the input string is "AAA rating". The iterative approach is pretty straight forward as illustrated below.

public class Iteration {

    public int countA(String input) {
        if (input == null || input.length( ) == 0) {
            return 0;
        }

        int count = 0;
        for (int i = 0; i < input.length( ); i++) {
            if(input.substring(i, i+1).equals("A")){
                count++;
            }
        }
        return count;
    }

    public static void main(String[ ] args) {
          System.out.println(new Iteration( ).countA("AAA rating"));     // Ans.3
    }
} 

Now, let's look at the recursive approach.

public class RecursiveCall {

    public int countA(String input) {
       
        // exit condition – recursive calls must have an exit condition
        if (input == null || input.length( ) == 0) {
            return 0;
        }

        int count = 0;
         
        //check first character of the input 
        if (input.substring(0, 1).equals("A")) {
            count = 1;
        }
        
        //recursive call to evaluate rest of the input 
        //(i.e.  2nd character onwards)
        return count + countA(input.substring(1)); 
    }

    public static void main(String[ ] args) {
        System.out.println(new RecursiveCall( ).countA("AAA rating"));    // Ans. 3
    }
}

Many find it harder to understand recursion, hence let's try it with a simple diagram.


Q.What concepts do you need to know to understand recursion?

A re-entrant method would be one that can safely be entered, even when the same method is being executed, further down the call stack of the same thread. A non-re-entrant method would not be safe to use in that way. For example, writing or logging to a file can potentially corrupt that file, if that method were to be re-entrant.

A function is recursive if it calls itself. Given enough stack space, recursive method calls are perfectly valid in Java though it is tough to debug. Recursive functions are useful in removing iterations from many sorts of algorithms. All recursive functions are re-entrant, but not all re-entrant functions are recursive.

Stack uses LIFO (Last In First Out), so it remembers its ‘caller’ and knows whom to return when the function has to return. Recursion makes use of system stack for storing the return addresses of the function calls.Java is a stack based language.



What follow up question(s) to expect?

Q. When would you use recursion? 
A. Recursion might not be the efficient way to code the above example and iterative approach will do the job, but there are scenarios where recursion is preferred as recursive functions are shorter, simpler, and easier to read and understand. Recursive functions are very handy in working with tree structures and avoiding unsightly nested for loops.

Q. What is a tail recursion, and why would you need it? Can you rewrite the above code with tail recursion?
A. Regular recursive function (aka head recursion) demonstrated above grows the size of the call stack. Each time the function calls itself, another entry has to be pushed onto the stack. The thing the function has to do before returning is add count with the result of countA(input.substring(1), assuming count is greater than 1, the computer has to evaluate count + countA(input.substring(1)), and in order to do that it must evaluate countA(input.substring(1)). This alse mean that you need to wait for the call to countA(input.substring(1) to complete so that you can add the value it returns with count. So, the last thing done here is actually the addition, not the recursive call.


What is the benifit of tail recursion? 

In tail recursion, the last thing done is the recursion and the addition would have been done before. You don't have any use for the old information because there’s nothing to do after the recursive call. You can throw out all of your old information and simply run the function again with the new set of parameters. This means you run with shorter call stack leading to lower memory usage and better performance.

Here is the above rewritten with tail recursion.


public class TailRecursiveCall {

 public int countA(String input) {

  // exit condition – recursive calls must have an exit condition
  if (input == null || input.length() == 0) {
   return 0;
  }
  
  return countA(input, 0) ;
 }
 
 public int countA(String input, int count) {
  if (input.length() == 0) {
   return count;
  }
  
  // check first character of the input
  if (input.substring(0, 1).equals("A")) {
   count = count + 1;
  }

  // recursive call is the last call as the count is cumulative
  return countA(input.substring(1), count);
 }

 public static void main(String[] args) {
  System.out.println(new TailRecursiveCall().countA("AAA rating"));
 }
}



Labels: , ,

Jul 5, 2012

Service versus component and SOA versus CBA?

Q. What is the difference between a component and a service?
A. Both components and services are self-contained functionality. Services enable your components to go across language boundary. For example, a component in .Net can talk to a component in Java through generalized messages in XML via Web services (i.e SOAP or RESTFul).

Components are made up of classes, interfaces, and EJBs. Components are used inside the programming boundary. The diagram below shows how you get self contained functionality and re-usability via components and services. Don't confuse yourself with some components being named like portfolio-service. This indicates it is a service layer containing the business logic. The portfolio-dao means portfolio data access object layer. The portfolio-interface contains the domain and POJO classes. These self contained components are used by both portfolio-client.ear, which is a web client and the portfolio-backend.ear, which is the service provider that exposes the business functions as web services across across the language boundaries. A .Net web client can still invoke the RESFul service. But the components in blue can only be used within Java programming boundary. The example shown below is Java based.



It is imperative to understand this difference not only when you are designing a system, but also when you are debugging your application. You need to know where to turn on the debugger for the same component used in 2 different JVM processes. That is the portfolio-client process and the portfolio-backend process. The components in blue are packaged into both deployable (i.e ear) artifacts. Similar color coded diagrams are required to communicate your design to your target audience. The color codes can indicate
  • Shared versus non-shared or reusable versus non-reusable component.
  • New versus existing component.
  • Buy (i.e. third-party ) versus build component. 

When designing a system, think as to

  • How these components are going to be packaged and deployed.
  • Dependencies between the packages and the components. Avoid cyclic dependencies.. 



Q. What is the difference between a Service Orieneted Architecture (SOA) and a Component Based Architecture (CBA) ?
A.  If you work with components, you are predominantly working with the code within the language boundary. For example, classes, interfaces, EJBs, JSF components, JavaScript widgets,  etc. If you work with services, you use some remote functionality over network under some contract. The contract will be in the form of an agreed XML message or JSON data.

Composing services into higher-level processes as in SOA is totally different than linking some components together into an application as in CBA.

A service contract is totally different from a component interface. A component can also offer its functionality over a network via RMI, IIOP, DCOM, CORBA, etc. But if you don't use an EJB as a service, then it's likely to be a component within your JEE application. A component can be exposed as a service. You can take an EJB component and expose it as a web service.

As the industry is moving from application oriented architecture to SOAwhere the applications are looked at as a set of services and components working together in fulfilling a certain business need.This is known as the SOBA (Service Oriented Business Applications). The services can be built with varying technologies like JEE, .Net, Ruby, etc. This architecture is used with the "single page web design".

Q. What is a Service Component Architecture (SCA)?
A.  The programming model that specifies how to create and implement services, how to reuse services, and how to assemble or compose services into solutions is achieved via SCA (Service Component Architecture). According to wikepedia, Service Component Architecture (SCA) is a software technology created by major software vendors including IBM and Oracle. SCA provides a model for composing applications that follow Service-Oriented Architecture principles.


SCA encourages organization of business application code based on components that implement business logic, and extend their capabilities through service-oriented interfaces to allow other components to consume functions through the service-oriented interfaces, called service references. SCA divides up the steps in building a service-oriented application into two major parts:
  • The implementation of service components  that provide services and consume other services.
  • The assembly of sets of components to build business applications, through the wiring of service references to services.


Note: If you are aspiring to be an architect, read up more on SCA (Service Component Architecture).


Labels:

Jul 4, 2012

Why does good API design matter?

Q. Why is a good API design important?
A.The Application Programming Interfaces (i.e. APIs) are fine grained services/libraries used by other applications, systems and libraries. A good API design improves flexibility, stability, and extendability of your application.

Now a days, applications are built as reusable components or services. A single page rich web page invoking multiple back end services via ajax  calls is very common. Services are used to put information into cloud storage, retrieving data from cloud storage,  validating data, updating a cloud based database, etc. This makes it even more important to carefully design your API.

Q. Give examples of a bad and good API designs in core Java API?
A. Here are some examples from Core Java API.

Bad Designs:
  • The Java Date and Calendar APIs are inconsistent and unintuitive. Firstly, it's full of deprecated methods and secondly, it makes it hard to do simple date operations. The Date and the Calendar classes are very complicated. Use the Joda Time API as it is well designed and easier to use.
  • Some of the legacy classes, which has synchronized methods everywhere are extended by other classes. For example, The Properties class extends the Hashtable, Stack extends the Vector class, etc.
Good Designs:
  • The Joda Time Library. This will be added to Java 7.
  • The Java Collection API. 

Q. What are some of the key considerations for a good API design
A. 

1. Define task oriented APIs

It is easier to add new methods. Deleting methods will break your client code or service consumers and deprecating methods can make your API more complicated to use.  Hence, favor fine-grained APIs that does a particular task. This also means you need to invoke many API methods to get the desired behaviour. When you are making remote calls over web services or cloud services, the performance may be adversely impacted. Good design is more important than just coding for performance. Premature optimization of code is an anti pattern. In rare instances where your profiling indicate performance issues, expose a number of fine grained services as a new coarse grained service. Remember -- it is easier to add new methods/services than deleting or deprecating existing methods/services. For example

When designing APIs, always think of the caller.

  • How will the caller use the API? 
  • Are method names and signatures intuitive enough for the caller? 

For example 

Bad design: A single method does too many things. The method name and signatures are ambiguous

public interface CashService { 
 BigDecimal getBalance (CustomerAccount account, BigDecimal currentBalance, List<TransactionDetail> txnDetails, 
                        boolean includeIncome, boolean includePending, boolean includeUnconfirmed) throws CashBalanceException;
}

Better design: Finegrained APIs that does a particular task. No ambiguous boolean flags or method names.

public interface CashService {

 BigDecimal getAvailableBalance (CustomerAccount account) throws CashBalanceException;

 BigDecimal getAutocashAvailableBalance ( BigDecimal currentBalance, List<TransactionDetail> txnDetails) throws CashBalanceException;
 
 BigDecimal getPortfolioBalance (BigDecimal portfolioBalance, List<TransactionDetail> txnDetails) throws CashBalanceException;;
 
 BigDecimal getRealtimeAvailableBalance (BigDecimal realtimeBalance, List<TransactionDetail> txnDetails) throws CashBalanceException;

}

The public interface methods defined above could internally (i.e. in the implementation) use a number of reusable private methods to perform the calculation. When exposing functionalities via a public interface, take a minimalistic approach to expose only those methods that will be required by the caller. Remember: it is easier to add methods than to remove.




2. Instead of the boolean flags use the type safe enum. The boolean true/false flags are ambiguous.

Bad design: boolean flags make the API difficult to understand

public interface UserService { 
 User getUser (String firstName, String surname, boolean isActive, boolean isMale, boolean ignoreSex) throws UserException;
}


Better design: the enum can take on the values like ACTIVE_MALE, ACTIVE_FEMALE, INACTIVE_MALE, INACTIVE_FEMALE, etc. As the method can take an array of user types with the varargs feature.

public interface UserService { 
 User getUser (String firstName, String surname, UserType...type) throws UserException;
}

3. Instead of passing many individual arguments corrupting the method signature, pass a well defined object that wraps all the required values.


public interface UserService { 
 User getUser (User user) throws UserException;
}
Where the User object looks like

public class User implements Serializable{

  private String firstName;
  private String surname;
  private UserType[] userTypes.
  //other attributes

  //getter and setters

  //toString(...), equals(...), hashCode() methods  
}

4. If you are using other collection types like List, Set, etc, make sure that you use generics as it makes it clear as to what type of object is stored. E.g. List<User>, Set<usertype>, etc.

5. Your API design must include the precondition check. The method implementation must fail fast after validating the relevant input. For example,

public User getUser (User user) throws UserException {

     if(user == null && (StringUtils.isEmpty(user.getFirstName()) || StringUtils.isEmpty(user.getSrurname()) ){
      throw new UserException("Invalid input: " + user);
  }
  
  
  ....

}

6. Providing good exception/error handling is essential to give the developers using your API an opportunity to correct their mistakes. Error messages should be clear and concise. Messages such as “Invalid input” are highly unhelpful. Also, avoid using a single exception object covering a number of very different possible errors. The decision to throw an exception, an error code, or a value like null to indicate "value is not found" must be carefully considered.

public User getUser (User user) throws UserException {

     if(user == null && (StringUtils.isEmpty(user.getFirstName()) || StringUtils.isEmpty(user.getSrurname()) ){
      throw new UserException("User's firstName and surname are required. Invalid input: " + user + "");
  }
  
  
  ....

}

In the above code, if an input validation fails it makes sense to throw an exception to indicate that an invalid input is supplied. It does not make sense to throw an exception if the designer anticipates that looking for a user that isn't there is not a common case and likely to indicate something that the caller would deal with the condition by substituting with a default "guest user" or prompting the user to register. In this case, returning a null value will be appropriate as this is not an exceptional condition. So, knowing the context in which an API is going to be used will allow you to make the right choice as to throw an exception or not. If your API requires a user to be present before it performs a task, then it makes more sense to throw a "UserNotFoundException".

With careful design of types and parameters, errors can often be caught at compile time instead of being delayed until runtime. Having said this, exceptions compared to true/false and error codes have several important advantages:


  • Exceptions cannot be ignored. If your code throws an exception the caller has to catch it to avoid getting an unhanded exception. The error codes or true/false can be ignored.
  • Exceptions can be handled at a higher level than the immediate caller. If you use error codes you may end up in situations where you at all layers of you application have to check for errors and pass them back to the caller. So, error codes are more appropriate at the highest layer. 


What ever technique you use, be consistent in your approach. Decide early on whether to use a checked or unchecked exception. If planning to use both, clearly have a plan as to when to use a checked exception and when to use an unchecked exception.

Labels:

Jul 3, 2012

Java coding question and answer on multi-threading

Core Java Coding Questions and Answers for beginner to intermediate level

Q1 Q2 Q3 Q4 Q5 Q6

Q. Can you review the given code and provide your feedback?

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {
 
 SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
 
 public String formatDate(Date input) {
      return sdf.format(input);
 }
 
}
A.

1. The code does not fail fast by checking for the preconditions.
2. The above code is not thread-safe as the SimpleDateFormat class is not thread-safe. If you check the API documentation, you will see

Synchronization: Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

Here is the illustration of the thread-safety issue with instance variables and the objects  they point to having methods not being synchronized.



As you could see, multiple threads are accessing the single instance of the "SimpleDateFormat" object via the reference "sdf". Since the methods in the SimpleDateFormat class are not properly synchronized, they are not thread-safe. 


The thread-safety issue can be resolved a number of ways.

Solution 1: Here is the thread safe code.


import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {
 
 private static final String SIMPLE_FORMAT = "dd/MM/yyyy";
 
 public String formatDate(Date input) {
  
  if(input == null){
   return null;
  }
  
  SimpleDateFormat sdf = new SimpleDateFormat(SIMPLE_FORMAT);//local variable
  return sdf.format(input);
 }
}


Here is the illustration of solution 1.




As you could see, the local variables are thread-safe as each stack will have its own "sdf" reference. The objects are always created in the heap.

Solution 2: While the solution 1 is thread-safe, it will end up creating too many SimpleDateFormat objects in the heap if a single thread invokes the formatDate(Date input) method multiple times. This can be overcome by creating the SimpleDateFormat objects as "per thread singleton" with the ThreadLocal class.

 

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {

 // anonymous inner class. Each thread will have its own copy of the SimpleDateFormat
 private final static ThreadLocal<simpledateformat> tl = new ThreadLocal<simpledateformat>() {
  protected SimpleDateFormat initialValue() {
   return new SimpleDateFormat("dd/MM/yyyy");
  }
 };

 public String formatDate(Date input) {
  if (input == null) {
   return null;
  }

  return tl.get().format(input);
 }
}



Learn more: Java multi-threading interview questions and answers: atomic operations

Solution 3: If  "SimpleDateFormat" were your own class, you could have appropriately made it thread-safe , for instance by applying method level or block level synchronization. Since, it is a third party library, you could use a decorator design pattern to wrap the  SimpleDateFormat in a new class say SimpleDateFormatWrapper. The SimpleDateFormatWrapper will   be made thread-safe.

Can someone write the code for the Solution 3?

Labels: ,