Thursday, July 30, 2009

JELDoclet and interface extraction

Today I was asked to help out another developer with some interface extraction work. This type of refactoring is normally tedious on a good day, but this task was especially difficult.

In this particular case, I was presented with 54 classes containing static methods implementing business logic. The developer in question was tasked with creating factories and company subsidiary specific implementations of these business methods, and felt that if I could pull all method signatures, parameter names, and documentation into a single mega-interface, he could easily split this up into smaller interfaces and construct his factories.

As you would expect, I quickly wrote a program based on reflection that almost entirely missed the point and came close to not having any of the information actually needed...

...in walks JELDoclet

JELDoclet is, well, a doclet that works with the javadoc tool to produce XML output rather than the HTML output we're all familiar with. Starting with an ant task:
<javadoc access="private" additionalparam="-J-Xmx1024m -d [output-dir]"
classpath="[classpath]"
packagenames="[list-of-packagenames]" sourcepath="[source-path]">
<doclet name="com.jeldoclet.JELDoclet" path="[path-to]\jeldoclet.jar"/>
</javadoc>

(replace [] with your project setup)

I very quickly had a jel.xml file that included something like the following:

<jelclass superclass="Object" visibility="public" superclassfulltype="java.lang.Object" fulltype="com.some.Clazz" type="Clazz" package="com.some">
<methods>
<method visibility="public" fulltype="java.util.List" returncomment="List of objects" type="List" name="getObjects" static="true">
<comment>
<description>Get the objects</description>
<attribute name="@param">
<description>refId ref ID</description>
</attribute>
<attribute name="@return">
<description>List of objects</description>
</attribute>
<attribute name="@throws">
<description>SomeException</description>
</attribute>
</comment>
<params>
<param fulltype="java.lang.Long" type="Long" comment="ref ID" name="refId"/>
</params>
<exceptions>
<exception fulltype="com.co.util.SomeException" type="SomeException" comment=""/>
</exceptions>
</method>
</methods>
</jelclass>

Now we're getting somewhere.

With the application of a simple xslt to the JELDoclet xml output, I have an interface definition. Try it out!

//com.some.Clazz
/**
* Get the objects
* @param refId ref ID
* @return List of objects
* @throws SomeException
*/
public java.util.List getObjects(java.lang.Long refId) throws com.co.util.SomeException;

No comments:

Post a Comment