Saturday, April 17, 2010

Overloads On Interfaces = Code Vomit

Whenever I see overloaded methods on an interface I puke in my mouth a little bit. Imagine seeing something like this:

public interface IPlayer {
  void Play(IMusic music);
  void Play(IMusic music, int volume);
}

This code declares an interface for a player that supports playing music with given volume, or playing music with some default volume level. So, why is that on the interface? Why is the fact that there is such a thing as a "default" value for level something that should pollute an otherwise simple interface for a player?

When overloads are used to hide default values for parameters they have no business being on an interface! Choose the most elaborate way to perform an action and make that the designated method. Only leave that designated method on the interface and take out all others. Implement default values outside of it. Think about this: why would every implementer of that interface have to supply exactly the same default value? And wouldn't it be confusing if they all supplied a different one? And how is that the responsibility of a player to know what the default value for volume is? Doesn't make any sense.

Now, overloads are also used for actually overloading functionality, meaning a method that can be performed on completely different inputs with different logic. Take this for example:

public interface IPlayer {
  void Play(IMusic music);
  void Play(IVideo video);
}

Make sense? NO! Interface segregation is one of the principles of SOLID design. Split that interface into two, one for each type of input. In fact, better make it a generic one since there's nothing else on it:

public interface IPlayer {
  void Play(T t);
}

You can still implement IPlayer and IPlayer in one class if you wish. But keep single responsibility in mind. One object should be responsible for one thing only and playing music and playing videos are two different things.