When Generics gets in the way

· Design PatternsTiger

I've read Egypt Java Experts' post about generics tips and even though I agree with the author's claim that the generics feature make for a better API design, sometimes it's just an overkill for the framework you're designing. I will take hplusplus' example AbstractProtocolFactory and HttpProtocolFactory and hope s/he won't mind. These classes were declared as:

public abstract class AbstractProtocolFactory<P extends Protocol, 
   C extends Configuration> { ... } 

public class HttpProtocolFactory extends 
   AbstractProtocolFactory<HttpProtocol, HttpConfiguration> { ... }
Part of designing a good API, especially when talking about protocols and configurations, is to make it highly configurable in a post-deployment state. This is often done by using the Strategy design pattern, and can be seen in Java's API in several occassions. For example, if I used message digests, I would use create a MessageDigest instance using MessageDigest.getInstance(String), making sure that the String passed is retrieved from a configuration file, so I could change the digest type later. Going back to hplusplus' example, I couldn't use such a thing. This is because the factory itself is generified, and in order to use it I need to provide the class types I require hard-coded. This might prove to be type-safer than using a string, but as I said before, some things need to be changed in a post-deployment state. If a year later I would decide to change the protocol type to an XML protocol instead of an HTTP protocol, I couldn't without redeploying my application. Another minor twist: In the example, hplusplus defines Protocol as:

public interface Protocol<C extends Configuration>
So a Protocol is defined to be used only with a certain type of Configuration. Because of this, the AbstractProtocolFactory could accidently be told to create a Protocol with a wrong type of Configuration, like HttpProtocol with XmlConfiguration. I would make a slight change like this:

public abstract class AbstractProtocolFactory<P extends Protocol<C>, 
  C extends Configuration> { ... } 
That way, it's type-safeer.

Comments (4)

Hossam Karim
Oh, thanks, I don't mind at all. I posted a reply to your comments here: http://www.egjug.org/node/230#comment-314 Cheers, Hossam Karim
Avah
You welcome. Glad to be of help. Let me see if I can respond to your comment, though (I can't respond in your blog as it requires registration and I'm in post-waking, pre-coffee mode now..) I understand you were making an API to create protocol instances of some specific protocol, so they are not interchangeable during post-deployment. In this case, using generics for creation IS a suitable manner; I just think that using configuration for that as well is a better practice - But as someone said in a thread lately, "There are good practices and there are real practices". This probably works better for you if you chose to do it this way. :)
Bihnar
You said: "If a year later I would decide to change the protocol type to an XML protocol instead of an HTTP protocol, I couldn’t without redeploying my application." I would say: you *shouldn't* make that change without redeploying your application. Making that kind of change in-place and in-production is like doing an entire new release but skipping QA!
Avah
Not true. For example, in compression, I would like to be able to change the version of data compression I use without recompilation and redeployment of my application and clients. Obviously some tests will occur, but you have to admit that as long as the new archiving (or in this case, protocol) supports the interface, (AKA as long as the new implementation is well tested), my application should still work as it is decoupled from the archive/protocol it uses! That's the whole idea of the strategy design pattern, after all.