Thursday, February 26, 2009

Introducing Unit Testing in Legacy code base

In big companies, developing a green field project is a rare privilege
... most of the time you will have to develop on a existing code base of
versatile quality - Not due to the skill of the developer more likely to
the history of the project, lack of code review and poor quality focus,
short term vs. long term risk -.

Anyway if you are not lucky you are facing a big spaghetti monster
calling other pasta entities in ways ranging from CORBA, RV, rmi, EJB,
ftp messaging ... Chances is that the code can't even run on your dev
machine, making development laborious and non productive.

There are 2 ways to deal with this problem

1 Status quo, self explanatory
2 Introducing unit test, mocking the internal and external monsters

1 : simple solution, not very rewarding but if the cost of solution 2
overcome the benefit that's the way to go
2 : long term benefit in development and quality. But costly

Though with a bit of method there are way to make 2 less costly, all you
will need is :

- A good refactoring dev environment, eclipse or idea
- Junit, XmlUnit
- XStream an xml serializer/desiralizer
- an UAT/Dev environment that runs.

1 - identify the part the function you need to test

you won't be able to test all the code, it is important to test a small
chain of the code lest that the mocking will be too complex.

It's likely that you can identify the function that is the entry and
exit point

Object f1(Object... args)

It is that function that we will try to unit test.


2 - record samples

your system is probably generating high complex object, based on high
complex entry. Trying to reproduce the graph manually is laborious and
sure to be incomplete. That's what we need to used XStream to record the
args and the output of the function in a uat environment, getting that
way real life object.



// the new method that will delegate to the old
// and dump in and out
Object f1(Object... args) {
dumpIn(args);

Object o = _f1(args);

dumpOut(o);
}

// was the real
Object _f1(Object args) {
...
}




3 - integrate your sample in your unit test

Now that you have sample with your input parameters and your expected
result you can start writing your unit test.

4 - mock the external call

It is likely that once you integrate the sample in the unit test, the
code will need to code external or internal component. you will need to
refactor that code in specific method that you will overwrite for your
test.



class F {
Object _f1(Object... args) {


// used to be inline
Object extInf = getExtInfo();
}


Object getExtInfo() {
....
}
}

class FTest extends F {

Object getExtInfo() {
return new MockObject();
}
}



If the object is to complex to Mock you can use the XStream to dump a
sample in uat environment.


5 - run the test !

6 - how to improve the solution

It is possible to create the list of test automatically by scanning the
samples directory e.g.. Making it easier to add sample and extend the
coverage of the test and behaviour.

This is an iterative process, it is not possible to make everything
testable in one go, take your time and surely step by step the quality
of your code will improve.

Friday, July 25, 2008

Dr. Horrible's Sing-Along Lyrics

Here

The Java Spirit

- Composition is better than inheritance
- Constructor are for initialization only
- destructor/finalizer are for debugging only
- Free resource explicitly
- Declare the interface not the type ie List myList; not ArrayList myList
- Optimize on metrics of a real system
- Use a proper development environment
- Don't believe the hype about closure, anonymous inner class cover 90% of the cases
- Properties are private or protected.
- Immutable is your friend.
- Don't pool object, we are in the 21st century
- Elegant code is code that is meaningful
- the most useful api are : Collections, common-lang, java.text

... To be continued

Wednesday, June 11, 2008

Too many open file descriptors, leak detection

In Java it is good practice to manually free the resources such as Streams, Connection. This is the consequence of the non deterministic property of the Garbage Collector. You object that is not reference might wait minutes before being process - or might even never -, so you can rely and the destructor - the finalize method - to do that - the finalizer make the collection of the object really costly-.

So if you open a Stream you should ideally do that :


InputStream is = null
try {
is = new FileInputStream(...);

...

} finally {
if (is != null) {
try { is.close(); ) catch(Exception e) { // IGNORE }
}
}


That's a lot of boiler plate code, and it's probably a good idea to use a Template pattern for that - look af Spring JDBCTemplate for example -.

What happen if you don't do that? That depends on how many file you are gonna open. It's really likely that the object is gonna get GC and FileInputStream as a finalizer where it closed itself.

But if your application uses file intensively you might end up with "Too many open file descriptors" errors. If you're lucky you have few entry points where stream are open, so you can easily fix it. Otherwise you will need a way to take the part of the code that are erronous.

What I propose under is to use Javassist to instrument the FileInputStrean and FileOutputStream class.

First we need a class that we would inject into the FileXStream to capture the states and detect the leaks.


package io;

public class LeakDetector {

private boolean closed;
private Exception trace;


public LeakDetector() {
trace = new Exception();
}

public void close() {
this.closed = true;
}

protected void finalize() {
if (! closed) {
printAlert();
}
}

private void printAlert() {
if (System.err != null) {
System.err.println("LeakDetector detected a leak from the object open at the following trace :");
trace.printStackTrace();
}
}
}



Then we need a class that instruments the FileXStreams


package io;

import java.io.IOException;
import java.util.concurrent.Callable;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.NotFoundException;

public class Instrumenter implements Callable<Object> {

private String[] clazzes;

public Instrumenter(String[] args) {
this.clazzes = args;
}

public static void main(String[] args) throws Exception {

if (args == null || args.length == 0) {
args = new String[] { "java.io.FileInputStream",
"java.io.FileOutputStream" };
}

new Instrumenter(args).call();
}

public Object call() throws NotFoundException, CannotCompileException, IOException {
ClassPool pool = ClassPool.getDefault();
for(String clazz : clazzes) {
instrument(clazz, pool);
}

return null;
}

private void instrument(String clazz, ClassPool pool) throws NotFoundException, CannotCompileException, IOException {
CtClass ctClass = pool.get(clazz);

ctClass.addField(CtField.make("private io.LeakDetector __io_ld;", ctClass));

for(CtConstructor cConst : ctClass.getConstructors()) {
cConst.insertBefore("__io_ld = new io.LeakDetector();");
}

for(CtMethod cMethod : ctClass.getMethods()) {
if (cMethod.getName().equals("close")) {
cMethod.insertBefore("__io_ld.close();");
} else if (cMethod.getName().equals("finalize")) {
cMethod.insertBefore("__io_ld._finalize();");
}
}

ctClass.writeFile("bin/java");
}
}


This class write the new FileInputStream in the bin/java directory. We need do assemble the LeakDetector and the new FileInputStream, FileOutputStream under the same jar. all you need to next is to run your application with the "-Xbootclasspath/p:leakdetector.jar" on the command line.

Note: Applications that use this technique for the purpose of overriding a system class in rt.jar should not be deployed as doing so would contravene the Java 2 Runtime Environment binary code license.


If you run the following code, with the bootclasspath set :


import java.io.FileInputStream;
import java.io.FileOutputStream;


public class DodgyIOClass {

public static void main(String[] args) throws Exception {


new FileOutputStream("c:/test.txt");

new FileInputStream("c:/test.txt");


Thread.sleep(3000);
System.gc();
Thread.sleep(3000);


}
}


It should prints :


LeakDetector detected a leak from the object open at the following trace :
java.lang.Exception
at io.LeakDetector.<init>(LeakDetector.java:11)
at java.io.FileOutputStream.<init>(FileOutputStream.java)
at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
at DodgyIOClass.main(DodgyIOClass.java:10)
LeakDetector detected a leak from the object open at the following trace :
java.lang.Exception
at io.LeakDetector.<init>(LeakDetector.java:11)
at java.io.FileInputStream.<init>(FileInputStream.java)
at java.io.FileInputStream.<init>(FileInputStream.java:66)
at DodgyIOClass.main(DodgyIOClass.java:12)

Wednesday, April 2, 2008

JSR 203 NIO 2 in Java 7

So it seems.

That would be probably one of the most awaited fix, a well design file system api.

no more


if (!file.delete()) {
// delete did not work but I don't know why
}

Friday, March 28, 2008

Java performance improvements touted


Java is not the slowpoke of old days and performance now matches or exceeds applications developed in C, technologists stressed Wednesday during a presentation at TheServerSide Java Symposium in Las Vegas.


From : DZone

Nice to see that written again.

Friday, March 14, 2008

IE 6 display = 'none' not working

see Here


Using


element.style.display = ''


instead solve the problem