Pages

Thursday, June 28, 2012

JAVA - Generics and design

What is generics?

Is a programming functionality which allows a type or method to operate on objects of various types while providing compile-time type safety. [1]  Generics add stability to your code by making more of your bugs detectable at compile time. [2]

The basic syntax in JAVA is <T extends MyClass>, where T is the generic variable to be used in the function implementation which in this case it will handle MyClass and all subclasses.  Imagine you need a function to sort objects of MyClass type and all their subclasses.  Without generics you will need a function per type.  But thanks to generics you can have only one function to handle all subclasses.


Example:  
Non-Generic Generic
public void MyFunction(MyClass aClass);
public void MyFunction2(AnotherClass aClass);
....
public <T extends MyClass> void MyFunction(T aClass);
Duplicate code to handle each subclass Only one function can handle all classes derived from MyClass


For detail implementaion information:

http://docs.oracle.com/javase/tutorial/java/generics/index.html


Generics are useful for...

The power of generics can be appreciated when designing components that other developers will use.  I find this specially important when you need to constrain the domain, but leaving it generic enough.  So why constrain the domain if we are talking about generics usage?  Because in my experience, developers take nasty shortcuts (supposedly to save time...) and use arguments type of strings or objects, or any wtfClass to hack there needs. Having a well define generic function will help other developers understand better the input of a method and avoid errors.


Example:  Generics and Design

In this example application we have an Activity which processes a ResultRes container.  The only purpose of an Activity is to modify the values of the ResultRes object.  You will see how using generics avoids unexpected errors and help developers understand better the classes needed to interact with an activity.

Download:  Source Code
Read the comments in the code for insight about the demonstration...

Parts of the application:

  • ResultRes - is the generic results container.
  • IntegerRes & StringRes - are sub-classes of ResultRes with different value types. 
  • ExecTemplate - is the generic class for activity execution.
    Notice how the template definition is the main issue in the design.
  • ActivityInt & ActivityString - are implementations of the ExecTemplate.
  • ExecGenerics - is just the Main() for testing the project. 

Main Program - usage of generics...

package generics.main;
public class ExecGenerics {

 /**
  * Example application about design and usage of generics.
  * The functionality is just to present how a background processing 
  * can cause exceptions due to bad design implementation which could
  * been avoided.
  */
 public static void main(String[] args) {
  
  boolean isUsingOriginal = true;
  
  // Set starter values...
  // This value will be modified by execute()
  IntegerRes i = new IntegerRes();
  i.setFieldValue(123);   
  StringRes s = new StringRes();
  s.setFieldValue("123");

  // print original values
  System.out.println(i.getFieldValue());
  System.out.println(s.getFieldValue());
 
  if (isUsingOriginal) {
   new generics.original.ActivityInt().execute(i);
   new generics.original.ActivityInt().execute(s); 
   // -- ^^^ this is LEGAL & PROBLEM.. execution will fail!
   new generics.original.ActivityString().execute(s);
  }
  else {
   new generics.improved.ActivityInt().execute(i); 
   // -- ^^^ watch how the helper shows the correct input class 
   // -- ^^^ (Ctrl+Space) inside parenthesis
   // new generics.improved.ActivityInt().execute(s); 
   // -- ^^^  this is NOT LEGAL NOW.. (won't compile)
   new generics.improved.ActivityString().execute(s); 
   // -- ^^^  watch how the helper shows the correct input class 
   // -- ^^^  (Ctrl+Space) inside parenthesis
  }
 
  // print values after processing
  System.out.println(i.getFieldValue());
  System.out.println(s.getFieldValue());  
 }
}


Execution Results

original (isUsingOriginal = true)
123
123
EXEC:  START    - class generics.original.ActivityInt
EXEC:  COMPLETE - class generics.original.ActivityInt
EXEC:  START    - class generics.original.ActivityInt
Exception in thread "main" java.lang.ClassCastException:
 generics.shared.StringRes cannot be cast to generics.shared.IntegerRes
 at generics.original.ActivityInt.performAction(ActivityInt.java:10)
 at generics.original.ExecTemplate.execute(ExecTemplate.java:11)
 at generics.main.ExecGenerics.main(ExecGenerics.java:32)
improved (isUsingOriginal = false)
123
123
EXEC:  START    - class generics.improved.ActivityInt
EXEC:  COMPLETE - class generics.improved.ActivityInt
EXEC:  START    - class generics.improved.ActivityString
EXEC:  COMPLETE - class generics.improved.ActivityString
999
999

Execute Template - Generic template design...

original
package generics.original;
public abstract class ExecTemplate {

 protected abstract void performAction(ResultRes res);
 
 public void execute(ResultRes res) {
   System.out.println("EXEC:  START    - " + this.getClass().toString());
   this.performAction(res);
   System.out.println("EXEC:  COMPLETE - " + this.getClass().toString());  
 }
}
improved
package generics.improved;
public abstract class ExecTemplate<T extends ResultRes> {

 protected abstract void performAction(T res);
 
 public void execute(T res) {
   System.out.println("EXEC:  START    - " + this.getClass().toString());
   this.performAction(res);
   System.out.println("EXEC:  COMPLETE - " + this.getClass().toString());  
 }
}

Activity - No casting needed when well designed...

original
package generics.original;
public class ActivityInt extends ExecTemplate {

 @Override
 protected void performAction(ResultRes res) {
  IntegerRes r = (IntegerRes) res;  // <-- Casting is required and not safe...
  r.setFieldValue(999);
 }
}
improved
package generics.improved;
public class ActivityInt extends ExecTemplate<IntegerRes> {

 @Override
 protected void performAction(IntegerRes res) {
  res.setFieldValue(999);  // <-- No casting required and enforces type
 }
}


Wednesday, June 6, 2012

IE9 - Corporate applications - Warning! - Rollback to IE8

IE9, a more beautiful web...  But does it works?

Preamble, this rant starts with my frustration over a legacy 3rd party solution used in the company which works in IE8 but NOT in IE9.  No compatibility mode or anything like it will fix the JavaScript failures / misbehaviours produced after switching to IE9.  So be careful and test your legacy corporate applications prior to rolling IE9.

In my case I had the source code for the legacy ASP .NET application and gave it a try to solve the issue.  For me the problem was the interaction between ASP .Net UpdatePanel and JavaScript execution.  For a moment I was able to hack something out and get it working..... BUT!!!.... then an IE9 security update came in and whatever that did, it totally mess up the "hack / fix".  Since fixing it wasn't my job, I had to move on and wait for the 3rd party to come up with the IE9 update which of course they want to get paid for.

Meanwhile I have to roll back to IE8 because IE9 was pushed to me over updates.  To my surprise, IE8 is not supported for Windows 7. In order to roll back IE8 in Windows 7, you need to know the trick

From nquinnell:
  1. Go to Control Panel, Uninstall Programs, then choose the option for Turn Windows Features On or Off.
  2. Uncheck the box before Internet Explorer 9. Let it uninstall.
  3. Go back to View Installed Updates on the left.
  4. Scroll down to Microsoft Windows until you see Internet Explorer 9. Uninstall it.
  5. Reboot.
  6. Go back to Control Panel, Uninstall Programs, and choose Turn Windows Features On and Off. This time, instead of showing Internet Explorer 9, it will show Internet Explorer 8. Check the box.
  7. IE8 installs. Reboot, and then put the icons back on your desktop.