RSS 2.0 New Entries Syndication Feed Atom 0.3 New Entries Syndication Feed

Show blog menu v



Use it



Sibling projects

RIFE powered

Valid XHTML 1.0 Transitional

Valid CSS!

Blogs : Latest entries

The sanitization of Ehcache's Cache constructors

We've all been there, you start with a class and a simple constructor that makes total sense. As time goes by, you keep adding features and the list of constructor arguments grows … and grows … until … it becomes unusable. This is exactly what happened with the Cache class in Ehcache.

The version 1.0 constructor looked like this:

public Cache(String name, int maxElementsInMemory, 
             boolean overflowToDisk, boolean eternal, 
             long timeToLiveSeconds, long timeToIdleSeconds)

However, with version 1.7 this turned into:

public Cache(String name, int maxElementsInMemory,
             MemoryStoreEvictionPolicy memoryStoreEvictionPolicy, 
             boolean overflowToDisk, String diskStorePath, 
             boolean eternal, long timeToLiveSeconds,
             long timeToIdleSeconds, boolean diskPersistent, 
             long diskExpiryThreadIntervalSeconds, 
             RegisteredEventListeners registeredEventListeners, 
             BootstrapCacheLoader bootstrapCacheLoader,
             int maxElementsOnDisk, int diskSpoolBufferSizeMB, 
             boolean clearOnFlush,
             boolean isTerracottaClustered,
             String terracottaValueMode, 
             boolean terracottaCoherentReads)

There are a lot of downsides to relying on constructor parameters like this:

  • the author of the class needs to continue to overload the constructors to add new parameters
  • users need to decide which overloaded constructor they want to use
  • users need to figure out what sensible default values are for the values that they're not interested in
  • it's very easy to accidentally put a value at the wrong place and provide wrong parameters
  • reading the constructor afterwards is a nightmare and can't be done without looking at the Javadocs at the same time, for instance:
new Cache("myCache", 10000, MemoryStoreEvictionPolicy.LRU, false, 
          null, true, 60, 30, false, 0, null, null, 0, 0, false, 
          true, "identity", true)

However there some advantages:

  • you can enforce which parameters are mandatory
  • at instantiation you can validate the constructor parameters
  • at instantiation you fully set up the instance without requiring users to call an initialization method

So, we decided to change the Cache constructor approach in Ehcache 2.0 and use a builder pattern with a fluent interface, keeping the advantages of the parameters approach but solving all the problems.

The version 2.0 constructor looks like this:

new Cache(CacheConfiguration config)

We then created a constructor in CacheConfigurator with the strict minimal number of parameters that are required for a cache to function:

public CacheConfiguration(String name, int maxElementsInMemory)

All the other parameters are implemented as fluent interface methods as well as regular setters and getters so that instances of the class can be used as beans:

public final CacheConfiguration clearOnFlush(boolean clearOnFlush) {
  return this;

This allows the example above to be rewritten like this:

new Cache(new CacheConfiguration("myCache", 10000)
      .terracotta(new TerracottaConfiguration()

The end results are that:

  • we can continue to expand the CacheConfiguration class without ever having to change the constructors of the Cache class
  • the user doesn't have to figure out the defaults for parameters he doesn't care about
  • the configuration parameters are self-explanatory by simply looking at the available API methods
  • anyone can read the usage of any Cache constructor and understand what each configuration value's purpose is
posted by Geert Bevin in Ehcache on Feb 17, 2010 6:34 PM : 7 comments [permalink]

Google web