Subscribe

  • Subscribe via XML
  • Subscribe via Bloglines
  • Subscribe via NewsGator
  • Subscribe via MyYahoo
  • Subscribe via Google
  • Subscribe via MyMSN
  • Add this blog to my Technorati Favorites!

Archive for the 'Java' Category

Using Java Enum for String-Based Dispatching

Thursday, December 17th, 2009

I ran across some (horrific) test code the other day that took this form:

public void testRunner(String toInvoke) {
  ...
  SimpleTest test = ...;

  if ("METHOD1".equals(toInvoke)) {
    ...
    test.invoke_method1(...);
    ...
  }
  else if ("METHOD2".equals(toInvoke)) {
    ...
    test.invoke_method2(...);
    ...
  }
  // and so on
}

There were probably 50 if/else blocks, occupying around 500 lines. Each block contained the exact same code, including try/catch exception handling, save for the actual method being invoked on the SimpleTest object. Essentially we’d like to be able to invoke a method based on the name of that method.

With a dynamic language like PHP, you can do a dynamic invocation easily:

$testObject = ...;
$methodName = ...;

$testObject->$methodName(...);

But you lose the benefits of a statically-typed language; it’s not until runtime that you find out whether the $methodName code actually exists.

So in Java you can clean up the if/else explosion by using an enum-based dispatch. You’ll need to know the strings in advance, but if you’re writing test cases that pass in strings, this is likely a non-issue anyway. Let’s set up an enum:

enum Dispatcher {
    METHOD1 {
        boolean invokeOn(Simple simple) {
            return simple.returnTrue();
        }
    },
    METHOD2 {
        boolean invokeOn(Simple simple) {
            return simple.returnFalse();
        }
    };

    abstract boolean invokeOn(Simple simple);
}

Which then allows us to write a very simple handler for the string input:

boolean dispatch(String methodName) {
    final Dispatcher d = Dispatcher.valueOf(methodName);
    return d.invokeOn(new Simple());
}

Now you are freed from having a 1-to-1 correspondence between your string input and the actual method name to be invoked. You’ve shifted this to the enumeration. And since an enumeration is an actual Java construct, you’ve recouped the ability for static analysis, refactoring, etc.

Of course there are other ways to dispatch based on the String value of a method. Reflection allows you to do this explicitly, and may have been an equally good, if not better, solution to the enumeration. Regardless, when you find yourself writing 500 lines of if/else, alarms should be going off.

For continued good reading on dynamic dispatching, have a look at a couple of good posts over at Java Clippings.

Use Caution with OSGi Exports

Thursday, September 17th, 2009

OSGi containers give developers a lot of power when it comes to packaging Java code. It helps to address some of the problems not (easily) otherwise solvable with the standard packaging mechanism provided by Java.

For example, I may need to have a public class that is available to my entire module. A class such that is not intended to be part of my public API. Call it a maintenance API, or internal API, or otherwise. The point is: It’s “public”, but not public.

Convention is typically used for such situations. My public API — the one intended for clients integrating with my system — might be exposed via the com.patrickschneider.api, while my maintenance/internal-only APIs might be exposed via something like com.patrickschneider.spi. Slap some Javadoc on top of this, make sure your SLA is up-to-date, and now you can tell your clients that they shouldn’t have been using those “spi” classes in the first place.

Fair enough. But wouldn’t it be nicer if you could avoid this in the first place? An OSGi container, can provide the measure of control, at runtime, to alleviate this problem. By using the ExportPackage manifest header, you retain explicit control over which packages will be available to other bundles / code. If it’s not exported, it won’t be seen.

This ability to hide and expose things so nicely also has some sneaky gotchas. The symptoms can range wildly; some of what I’ve personally seen are arcane errors including VerifyError and NoClassDefFoundError. Anytime something like this pops up, it seems that there is a ClassLoader to blame. And when dealing with OSGi, class loading is a huge deal.

Take for example the ability of an OSGi bundle to package within itself other jar files. These are often packaged inside of a “lib” directory inside of the bundle; this is arbitrary, though, and must be specified through the Bundle-ClassPath header in the bundle manifest. Crack open such a bundle, and you will see each jar in a comma-separated list. You’ll likely also see a reference to the root of the bundle, specified with by a full-stop (”.”).

The best piece of advice I can give regarding packaged dependencies: Do not export their contents.

Why would you export a dependency’s contents? Well, the thinking might go something like this… “I have Bundle A, and it packages CGLib. We are introducing Bundle B, and it needs to do some code generation of its own. No need to re-package the dependency; let’s just export what B needs from A.”

If your programming in a bubble, you might get away with this. Bundle B utilizes some CGLib code exported from Bundle A, and you’re on your merry way. But remember that Exports are available to the entire OSGi container — other bundles that use the packaged dependency may be affected by your Export choices. This is especially worrisome in the case of our example, where we’ve chosen to partially export the dependency. The class loading details get pretty hairy, so again, I’ll re-emphasize: Do not export packaged dependencies from an OSGi bundle.

Java Naming Convention: “as” and “to”

Friday, August 7th, 2009

I recently heard of an interviewing tactic that goes like this: Present the candidate with a couple of slightly obfuscated methods. The challenge is to read through the code and name the variables and methods. This is a very straight-forward task, but the more I thought about it, the more powerful I realize it is.

How and when and why a developer applies a specific name to a variable, method, class, etc. speaks volumes to that person’s abilities. Does he understand what the method does? Is he clearly communicating this to others? Is he cognizant of idioms and other common usage patterns for this specific scenario?

In a strongly-typed language like Java, moving data around from type to type is the name of the game. Transformational and coercive methods are ubiquitous. And yet, it is so easy to misapply even the simplest of words and, in doing so, convey an entirely different message than your intention.

Let’s say you have class A and you need to add a method to it that returns an instance of class B based on A. A very natural thought process for this might go something like: “I need to convert A to B.” And so you write this in your code:

class A {
   ...

   /**
    * Converts this instance to an instance of B.
    */
   B toB() { ... }
}

Simple enough. But our javadoc is somewhat vague: If I modify the result of this method call, will my original instance of A be modified? In other words, is this a copy of the instance of A, or is it the actual instance of A masquerading as an instance of B? Despite the vagueness, let’s say you publish this method, and people start using it. How can they expect it to behave? We should have thought through the exact requirements first. But we also needed to take extra care in naming the method.

The Java libraries have already established a convention for how we should interpret “to” in front of a method name. Object defines toString(), which returns a String representation of the object. Since all Strings are immutable, it is very clear that we cannot alter the originating instance by munging the String.

On the other hand, Arrays defines asList(T… a). Using “as” for the prefix in the above method may have been just as valid, depending on what our true intentions were. But the conventional meaning is completely different. This method is described in the javadoc as follows:

Returns a fixed-size list backed by the specified array. (Changes to the returned list “write through” to the array.)

So we see here that we’re dealing with the originating array, but we are able to access it as if it were a List. Here are their conventional meanings in the general sense:

  • asType — returns an instance of Type backed by the original instance; modifications to the returned value are reflected on the originating object.
  • toType — returns an instance of Type not backed by the original instance; modifications to the returned value are not reflected on the originating object.

Personally, I recall the distinction between the two by remembering the Java Object and Arrays APIs — these APIs are common enough that I don’t have to think about it much.

Now let’s go back to our toB method. A perfectly valid interpretation, were someone attempting to call that method, would be to assume the convention holds true. If we take it at face value, we should expect that we are given an object that, when modified, will have no effect on the original instance of A. If this is indeed the case, we should update our javadoc to be more specific. Even though conventions are useful, not everyone obeys them. Your javadoc should clearly support the typical notion of this usage.

Here’s the updated code, with an example of an “as” method thrown in, while we’re at it:

class A {
   ...

   /**
    * Generates an instance of B based on the current object.
    * Mutative operations on the returned value will have no
    * effect on the current object.
    */
   B toB() { ... }

   /**
    * Returns an instance of B backed by the current object.
    * Mutative operations on the returned value will be
    * reflected on the current object.
    */
   B asB() { ... }
}

Again, it’s easy to remember the difference: Just think asList vs. toString.

Maven and Perforce: Forget about SCM Location

Wednesday, October 17th, 2007

Because of SCM-229, you no longer need to specify the <scm/> stuff in your POM. Because anything you checkout from Perforce always knows from where in the source it originated (via the ClientSpec), Maven can now dynamically determine where this code is, what should be labeled (during release), and won’t complain if this value is completely wrong.

This last point should be taken seriously though — putting a real value in the <scm/> element could lead to confusion. For my projects, I use an SCM section that looks like this:

...
<scm>
  <connection>scm:perforce://fake-scm-paths</connection>
  <developerConnection>scm:perforce://see-SCM-229</developerConnection>
</scm>
...

The point being that this is clearly a fake SCM location, but also points you to the reason why (SCM-229). This is especially useful when branching — you don’t need to update the SCM location in order to release your project from a branched location in source control.

Oh — one important thing to note is which version of the release plugin you are using. SCM-229 was fixed in version 1.0-beta-4 of maven-scm-provider-perforce, which is used in the 2.0-beta-6 version of the maven-release-plugin. So if you are not already explicitly declaring the versions of your plugins (you should be!), you’ll need to ensure your POM has this info:

<build>
  ...
  <plugins>
    ...
    <plugin>
      <artifactId>maven-release-plugin</artifactId>
      <version>2.0-beta-6</version>
    </plugin>
    ...
  </plugins>
  ...
</build>

Enjoy :)

© 2004 - 2012 Patrick Schneider, All Rights Reserved.