December 2006

The binary dependency boogy

Sooner or later, every software project ends up relying on some binary module, which could could be a third-party library or another project in compiled form. In the Java world, these are jar files (remember back in the Age of Aquarius when they were zip files too?!) and on the Microsoft platform they’re dlls.

Given that it’s pretty much a universal truth that eventually you’ll have to come up with a binary dependency management scheme, I’m amazed with the myriad different ways I’ve seen this handled. Two of the most common techniques I’ve seen are:

  • Place all libraries on a shared drive
  • Place all libraries in a lib folder underneath the project’s root

Of course, these strategies work; however, they aren’t optimal. Placing all libraries on a shared drive becomes a maintenance nightmare if they are haphazardly placed there– like in one giant directory. Then of course, you have the issue with drive mapping, which works fine if everyone’s on the same OS.

Placing libraries in a specific project folder (and of course, adding them to an SCM) is a good strategy in that a project’s dependencies are managed within the project itself. If you end up having multiple projects that have the same dependencies; however, you end up with the same jar file, for example, copied throughout an SCM, which has always seemed inelegant to me.

I, instead, prefer a binary dependency management mechanism spearheaded by the Maven project, which can be emulated in Ant, NAnt, and any other build platform that supports HTTP gets. Using this scheme, dependencies are placed on a web server and are versioned via a naming scheme. During the build process, required libraries are downloaded to the local machine and are included in the classpath for compilation, runtime execution, etc.

The beauty here is the naming scheme. For example, say I’m building a project which uses JUnit for its test framework; consequently, to compile and run resulting tests, the build process requires JUnit’s jar file in the classpath. If my project requires version 3.8.1, then I can create a few properties to represent the dependency as follows:

<property name="junit-jar" value= "junit-3.8.1.jar" />

Then I need a disco place to download it from– I can either set up my own web server for the project, or use a publically available one, such as ibiblio.org, which in that case, the download URL would be the base: http://www.ibiblio.org/maven/junit/jars/ and then the jar file: junit-3.8.1.jar.

I also need to specify a place to download dependencies to, which in my case is set via a property:

<property name="libdir" value="target/lib" />

Note too, I can have multiple repositories from which to obtain dependencies from, so I can create a repository property as well. Putting it all together yields a get that looks like this:

<get dest="${libdir}/${junit-jar}" usetimestamp="true"
       ignoreerrors="true"
       src= "${repo-base}/junit/jars/${junit-jar}" /> 

Creating a classpath is as easy as including all the jars in the target/lib directory as I’ve done below.

<path id="build.classpath">
  <fileset dir="${libdir}">
   <include name="**/*.jar">
   </include>
  </fileset>
</path>

Of course, targets which compile code or run tests, would then depend on the dependencies being present; accordingly, they can specify a depends clause which links back to a target that performs a series of gets.

<target name="compile" depends="get-deps">....</target>

The get-deps target also has the hip ability to skip downloads should the libraries already be in place; therefore, a noget property is available as shown below:

<target name="get-deps" unless="noget" depends="init">...</target>

I should add that there are more sophisticated mechanisms available for Ant which handle dependency management– Ivy is one such project that is probably the most feature rich. Both Ivy and Maven2 support the notion of transitive dependencies, which is way disco and limits a lot of the grunt work when specifying dependencies. If you’ve ever done this with something like Hibernate or Spring, you’ll know what I mean.

What I’ve shown here, by the way, is applicable in NAnt as well using its get task.

The next time you find yourself unable to build because the link to the share drive is down or you are unsure what exact version of a library is required for compilation, consider using the Maven scheme for dependency management– it’ll free up some copasetic time for more disco dancing.

The weekly bag– Dec 29

Last weekly bag of the year, baby!

The weekly bag– Dec 22

A day late but nevertheless, a truly disco list:

Discovering XMLUnit the easy way

From time to time, you may need to verify the structure or content of XML documents– in this month’s In pursuit of code quality series, “Discover XMLUnit” shows you why you don’t want to use String comparisons to verify the structure and content of XML documents. Then it introduces XMLUnit, a hip XML validation tool and shows you how to use it to validate XML documents.

Also too, don’t forget to get your groove on at the “Improve Your Java Code Quality” forum!

Groovy in Action ebook is out, baby!

Manning’s Groovy in Action is now available as an ebook; what’s more, the print edition will ship the first week of January, man. The timing couldn’t be better– Groovy is quickly approaching a 1.0 status. Also don’t forget to check out aboutGroovy.com for more news and information on this hip language!

The weekly bag– Dec 15

Keep on disco dancing with this collection baby!

The meaning of code metrics

What assumptions come to your mind when you view this unhip bank account?

account-simple

Based upon the amount of cash found in both the savings and checking accounts, you could probably presume one thing– this person doesn’t have a lot of money. If that were my bank statement around the beginning of the month, I’d find myself in a world of stress worrying about a mortgage, for one thing.

But what if I told you that the account holder is 5 years old? All of a sudden, you may find yourself making different assumptions– perhaps you’re impressed that this 5 year old has both a checking and a savings account!

Clearly, background information on the owner of the account certainly helps put into perspective how one would view the funds available. Similarly, with software metrics, the same lesson holds true– the application being measured needs to be considered in context during analysis . Applications built to run on a wrist watch will most likely yield metrics quite different and even considered harmful if they we obtained from a copacetic web application, for instance.

Take another look at this bank account below.

account-simple

Having read this far, you may be thinking this account may indicate a positive balance if the owner is 5 years old, but probably a negatively focused balance should the owner be an adult with a family to support. Now take a look at the next bank account statement.

account-withcredit

Now, regardless of the bank account owner’s age, this person most likely has some debt challenges. If this person is 5, perhaps you could infer fraud or identity theft. If this person is a father of a few children, could you infer the same things? Perhaps so. Perhaps not.

The point being, of course, is that once another piece of data has been introduced, many assumptions are altered– the same holds true for software metrics. You can view a few of them in context and infer one aspect of quality, perhaps, but once another metric has been introduced, your inference on quality can be totally changed . Just like viewing one’s checking and savings accounts without viewing any debt associated with a credit card yields a partial picture, the same thing holds for metrics– they only give you a partial picture of an application, so to speak.

Take a look at the account below.

account-highcash

What inferences do you draw about this account’s holder? At first look, things seem to be ok (depending on one’s cash requirements), right?

Now take a look at a snap shot of the same account from yesterday.

account-highcash-yesterday

Clearly there has been a rather negative change in the accounts. The change isn’t terribly concerning though– perhaps a mortgage was paid. Now examine a neat-o snap shot of the same account from a week ago.

account-highcash-lastweek

Having examined three snap shots of this account that span roughly a week, what deductions can you draw? Clearly, in the context of time, these snap shots indicate a negative trend, by which various inferences can be made, such as that this person is losing money. But the data has only been viewed over two weeks– what if tomorrow is pay day? How do you think the accounts will look then, man?

Also too, what happens when you add in the other contexts from above, such as the age of the account’s holder and a snap shot of the person’s credit card balance? If you add the credit card balance to this mix of cash, I’m betting your outlook may be less positive, right?

Now examine another three snap shots of an account. Below is today’s balance.

lowcash-today

Next, have a look at last month’s balance. What do you notice?

lowcash-lastweek

Check out the balance below from three months ago. Notice how the balance has demonstrated a clear growth.

lowcash-lastmonth

Both trend images sets show different patterns– one demonstrates a negative trend and the other demonstrates a growth pattern. What’s more, each initial balance may have initially given you a different impression. With code metrics, the same holds true– they should be viewed over time as the trend they may exhibit gives a more realistic view.

With code metrics, keep three things in mind:

  1. They are objective measures of something but they must be applied subjectively.
  2. Metrics should be viewed in concert with other metrics to enable a more precise picture.
  3. These same metrics should be viewed over time to produce a more accurate picture as to how things are progressing or have progressed.

Of course, there is still the question on what the data actually means; however, before you can begin to derive information from numbers, you must understand how to actually view them. Dig it?

The weekly bag– Dec 8

Keep on disco dancing with these hip links:

Smokin’ early performance testing

Performance testing is usually left for last in hip application development cycles– not because it’s unimportant, but because it’s hard to do effectively with so many unknown variables. IBM developerWork’s “In pursuit of code quality: Performance testing with JUnitPerf” makes the case for performance testing as part of the development cycle and shows you two easy ways to do it with Mike Clark’s JUnitPerf framework. Check it out, man!

Because it’s your bag baby, don’t forget to let it all hang out at the “Improve Your Java Code Quality” forum too!

Hip XML testing with Groovy

Verifying XML documents has always been the strength of XMLUnit; however, I’ve often found that this JUnit extension is challenging when trying to verify specific portions of a hip XML document. Sure, XMLUnit supports XPath , but XPath is somewhat of a pain (especially if you aren’t an adept XPather).

For example, given the following copasetic XML document, I’d like to verify the exact value of the name attribute of the first Class element.

<DependencyReport date="Wed Dec 31 21:30:00 EST 1969">
  <FiltersApplied>
    <Filter pattern="java|org"/>
    <Filter pattern="junit."/>
  </FiltersApplied>
  <Class name="com.vanward.test.MyTest">
    <Dependency name="com.vanward.resource.XMLizable"/>
    <Dependency name="com.vanward.xml.Element"/>
  </Class>
  <Class name="com.xom.xml.Test">
    <Dependency name="com.vanward.resource.XMLizable"/>
    <Dependency name="com.vanward.xml.Element"/>
  </Class>
</DependencyReport>

Using XMLUnit and XPath, if you’d like to verify that the first Class element’s name attribute value is com.vanward.test.MyTest, you could use the following disco XPath expression:

//Class[1][@name='com.vanward.test.MyTest']

This XPath expression, in concert with XMLUnit, yields the following JUnit test case that must extend XMLUnit’s XMLTestCase due to the call to assertXpathExists:

public void testToXML() throws Exception{
 BatchDependencyXMLReport report =
   new BatchDependencyXMLReport(new Date(), this.getFilters());
 report.addTargetAndDependencies("com.vanward.test.MyTest",
    this.getDependencies());
 report.addTargetAndDependencies("com.xom.xml.Test",
    this.getDependencies());

 assertXpathExists("//Class[1][@name='com.vanward.test.MyTest']",
                report.toXML());
}

In order to verify exact portions of an XML document within XMLUnit, I must have a working knowledge of XPath and must extend XMLUnit’s XMLTestClass. Also too, debugging XPath expressions with XMLUnit isn’t exactly easy either– you end up relying on test case successes or failures to ascertain if your expression is actually valid (but what a great way to verify them, I suppose!). Clearly, verifying exact XML values in XMLUnit is possible, but it could be easier.

Using Groovy, traversing XML documents and obtaining values is, in my opinion, amazingly simple and is much more easy to grasp than XPath. For example, verifying the same exact attribute value can be done as follows:

void testToXML() {
 def report = new BatchDependencyXMLReport(new Date(), this.getFilters())
 report.addTargetAndDependencies("com.vanward.test.MyTest",
    this.getDependencies())
 report.addTargetAndDependencies("com.xom.xml.Test",
     this.getDependencies())

 def doc = new XmlSlurper().parseText(report.toXML())
 def clazzes = doc.Class
 assertEquals("class name should be com.vanward.test.MyTest",
   "com.vanward.test.MyTest", clazzes[0].@name.text())
}

In this example, you only need to work with Groovy’s XmlSlurper class and you’re able to traverse XML nodes as if they are a call graph. As you can see, after the XmlSlurper class is initialized with my document, I am able to grab a reference to the collection of Class elements by asking the root node directly by specifying the element name, which, because it’s my bag, is Class.

Once I have this collection of elements, I can simply reference them similar to XPath, but in Groovy’s case, the access method is 0 based (which is array based access that you learned in CS101). If you look at the first XPath example, it’s 1 based (see the [1] reference?). Accessing attributes is also similar to XPath via the @ symbol and obtaining their value requires the text call.

Given these dynomite semantics, the same XML navigation from the first code example is a much more natural clazzes[0].@name.text(). What’s more, the beauty here is that you’re not dealing with Strings either. Granted, the two examples are slightly different– in the pure Java one, due to the limited API of XMLUnit, I’m forced to assert that an expression exists and in Groovy, I can assert that a value exists. The latter feels more flexible to me.

Using Groovy’s innate XML handling ability means XPath isn’t required. Which is easier to comprehend to you– //Class[1][@name='com.vanward.test.MyTest'] or clazzes[0].@name.text()? The next time you find yourself wanting precise access to portions of an XML document, put Groovy to the test– you’ll find it quite groovy. Dig it?

Next »