Are empty interfaces code smell? [closed]
Solution 1:
Although it seems there exists a design pattern (a lot have mentioned "marker interface" now) for that use case, i believe that the usage of such a practice is an indication of a code smell (most of the time at least).
As @V4Vendetta posted, there is a static analysis rule that targets this: http://msdn.microsoft.com/en-us/library/ms182128(v=VS.100).aspx
If your design includes empty interfaces that types are expected to implement, you are probably using an interface as a marker or a way to identify a group of types. If this identification will occur at run time, the correct way to accomplish this is to use a custom attribute. Use the presence or absence of the attribute, or the properties of the attribute, to identify the target types. If the identification must occur at compile time, then it is acceptable to use an empty interface.
This is the quoted MSDN recommendation:
Remove the interface or add members to it. If the empty interface is being used to label a set of types, replace the interface with a custom attribute.
This also reflects the Critique section of the already posted wikipedia link.
A major problem with marker interfaces is that an interface defines a contract for implementing classes, and that contract is inherited by all subclasses. This means that you cannot "unimplement" a marker. In the example given, if you create a subclass that you do not want to serialize (perhaps because it depends on transient state), you must resort to explicitly throwing NotSerializableException (per ObjectOutputStream docs).
Solution 2:
You state that your function "returns entirely different objects based on certain cases" - but just how different are they? Could one be a stream writer, another a UI class, another a data object? No ... I doubt it!
Your objects might not have any common methods or properties, however, they are probably alike in their role or usage. In that case, a marker interface seems entirely appropriate.
Solution 3:
If not used as a marker interface, I would say that yes, this is a code smell.
An interface defines a contract that the implementer adheres to - if you have empty interfaces that you don't use reflection over (as one does with marker interfaces), then you might as well use Object
as the (already existing) base type.
Solution 4:
You answered your own question... "I have a function that returns entirely different objects based on certain cases."... Why would you want to have the same function that returns completely different objects? I can't see a reason for this to be useful, maybe you have a good one, in which case, please share.
EDIT: Considering your clarification, you should indeed use a marker interface. "completely different" is quite different than "are the same kind". If they were completely different (not just that they don't have shared members), that would be a code smell.
Solution 5:
As many have probably already said, an empty interface does have valid use as a "marker interface".
Probably the best use I can think of is to denote an object as belonging to a particular subset of the domain, handled by a corresponding Repository. Say you have different databases from which you retrieve data, and you have a Repository implementation for each. A particular Repository can only handle one subset, and should not be given an instance of an object from any other subset. Your domain model might look like this:
//Every object in the domain has an identity-sourced Id field
public interface IDomainObject
{
long Id{get;}
}
//No additional useful information other than this is an object from the user security DB
public interface ISecurityDomainObject:IDomainObject {}
//No additional useful information other than this is an object from the Northwind DB
public interface INorthwindDomainObject:IDomainObject {}
//No additional useful information other than this is an object from the Southwind DB
public interface ISouthwindDomainObject:IDomainObject {}
Your repositories can then be made generic to ISecurityDomainObject, INorthwindDomainObject, and ISouthwindDomainObject, and you then have a compile-time check that your code isn't trying to pass a Security object to the Northwind DB (or any other permutation). In situations like this, the interface provides valuable information regarding the nature of the class even if it does not provide any implementation contract.