Thursday, December 06, 2007

Factory Methods over Constructors

There is a lot of talk about how singles are harmful. Many of them make very good points. However, I think one thing that is generally missing from the discussion is a small pattern that is almost universally used when implementing singletons.

I mean of course, the factory pattern.

Very few people provide public access to singleton variables, they are usually provided via an instance() method. The class is its own factory object.

Why is this good?

It means you don't have to use singletons, though they could be an option. Say a class needs to operate on a non-thread safe class (an xml transformer for example), or it uses a library of uncertain thread safety. Instead of having a static reference to the instance that is returned by the factory method, it could use a ThreadLocal to ensure that each thread has its own instance. This gives the ability top address issues with threads while gaining the benefits of a singleton.

Another use of the factory pattern can be object pooling. If the object is pretty heavy weight, or requires a lot of set-up, you obviously don't want to have too many instances floating around or don't want to create them too frequently. You could write your own pooling implementation or use the Jakarta Commons Pool.

If a singleton is the right thing to do, then it should obviously be used. Consumers of the class should not have to worry about whether or not it is a singleton. Of course, this also means you shouldn't be storing state information in the class (but, you knew that).

What does this mean for testing? A private constructor is still going to prevent over-riding the class to create "truly" new instances. This means another option will have to be taken.
Perhaps the easiest is to over-load the factory method with one that always returns a new object. If the scope of this method is limited to package level, then little more than the test case should have access. The problem here is, an overly cautious developer may discover the method and use it instead of the factory class.

I would propose testing the class the same as it will be used. If there is a concern about internal state, write tests to cover it. Besides, maintaining internal state in class provided by factory methods is generally a bad practice. Try writing tests to ensure this isn't happening.

Another option could be to refactor so that a separate factory object is used, and it could be over-ridden to provide a class for testing...

Though there are problems with singletons, don't throw out the baby with the bath water. The nature of a good singleton makes it easy to do things beside a single instance in a very transparent way.

Labels: , , , , ,

permalink
Links to this post
1 comments

Wednesday, December 05, 2007

XML to JSON

Recently, I came upon the need to provide AJAX support for a site where the XML data comes from a remote site.

Security settings on the browsers prevent making a request to a non-originating server so, the solution is to create a proxy servlet.

Also, parsing XML generally sucks, parsing it with javascript is worse. To deal with this, the ideal solution is to return JSON instead of XML.

So, with a combination of the Jakarta Commons HttpClient (its just more robust than the java.net.HttpURLConnection), a cool schema to convert xml to json, the quintessential xml/xslt transformer, and a little glue, a solution is born.

Some things to note.
Use the version of the schema in the issues part of the Google Code page. It contains some useful bug fixes.
The transformer should work on streams instead of files (of course).
Be smart about thread handling with the HttpClient (cache results to minimize use of the HttpClient if you expect any kind of serious traffic).
Be sure the XML file is encoded the way you expect (UTF-8, ISO-8859-1, or whatever). If you get some crappy, I mean mis-encoded data, you can fix it when creating the InputSource:
Source source = new StreamSource(
   new InputStreamReader(xmlIn,"ISO-8859-1"));


For unit/integration testing, I highly recommend using the Rhino JavaScript interpreter. You can feed the JSON and your script to it to ensure things work the way you expect. A little jUnit to run things and life is good.

Labels: , , , ,

permalink
Links to this post
1 comments