Method overloading is taught in OOP 101, but there are times when it should be avoided like plague. Let me explain ...
During a recent implementation of Caching solution, I had to create a CacheManager which could support the creation and management of different types of Cache types - say file system based, memory based, db based etc. Each cache type comes with different options. For example, file based system could monitor a file as a dependency, which the DB based cache does not.
A typical example of different overloads is as follows ...
interface ICache {
void Add<T>(string key, T value)
void Add<T>(string key, T value, string filename);
void Add<T>(string key, T value, DateTime absoluteExpiration);
void Add<T>(string key, T value, CacheDependency dependencies);
void Add<T>(string key, T value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration);
void Add<T>(string key, T value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration,
CacheItemUpdateCallback onUpdateCallback);
void Add<T>(string key, T value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration,
CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback);
}
So how do we create an efficient caching solution without creating overloads for each supported options by a cache type.
The solution is to create a CacheOptions class that has a union of all options supported by all the cache types. So the example above can be rewritten as follows ...
interface ICache {
void Add<T>(string key, T value, CacheOptions options);
}
class CacheOptions {
public string FileName { get; set; }
public DateTime AbsoluteExpiration { get; set; }
public TimeSpan SlidingExpiration { get; set; }
public CacheDependency Dependecy { get; set; }
public CacheItemPriority priority { get; set; }
public CacheItemUpdateCallback OnUpdateCallback { get; set; }
}
This does a few things for us ...
- Simplify ICache interface, let each implementation work with the CacheOptions
- Everytime we have a new Cache type, we don't have to modify the interface ICache, and thereby the other implementations
- We can also initialize (with non-null values) some properties which are optional parameters. This results in cleaner code ...
Before ...
SomeCahce.Add("key", new object(), new CacheOptions() { AbsoluteExpiration = DateTime.MaxValue });
After ...
class CacheOptions {
public CacheOptions() {
// Default values
AbsoluteExpiration = DateTime.MaxValue;
}
...
}
SomeCahce.Add("key", new object(), new CacheOptions());

