Constructor-Only Subclasses – Identifying Anti-Patterns

anti-patternsdesign-patternsinheritanceobject-oriented

I was having a discussion with a co-worker, and we ended up having conflicting intuitions about the purpose of subclassing. My intuition is that if a primary function of a subclass is to express a limited range of possible values of its parent, then it probably shouldn't be a subclass. He argued for the opposite intuition: that subclassing represents an object's being more "specific", and therefore a subclass relationship is more appropriate.

To put my intuition more concretely, I think that if I have a subclass that extends a parent class but the only code that subclass overrides is a constructor (yes, I know constructors don't generally "override", bear with me), then what was really needed was a helper method.

For example, consider this somewhat real-life class:

public class DataHelperBuilder
{
    public string DatabaseEngine { get; set; }
    public string ConnectionString { get; set; }

    public DataHelperBuilder(string databaseEngine, string connectionString)
    {
        DatabaseEngine = databaseEngine;
        ConnectionString = connectionString;
    }

    // Other optional "DataHelper" configuration settings omitted

    public DataHelper CreateDataHelper()
    {
        Type dataHelperType = DatabaseEngineTypeHelper.GetType(DatabaseEngine);
        DataHelper dh = (DataHelper)Activator.CreateInstance(dataHelperType);
        dh.SetConnectionString(ConnectionString);

        // Omitted some code that applies decorators to the returned object
        // based on omitted configuration settings

        return dh;
    }
}

His claim is that it would be entirely appropriate to have a subclass like this:

public class SystemDataHelperBuilder
{
    public SystemDataHelperBuilder()
        : base(Configuration.GetSystemDatabaseEngine(),
               Configuration.GetSystemConnectionString())
    {
    }
 }

So, the question:

  1. Among people who talk about design patterns, which of these intuitions is correct? Is subclassing as described above an anti-pattern?
  2. If it is an anti-pattern, what is its name?

I apologize if this turns out to have been an easily googleable answer; my searches on google mostly returned information about the telescoping constructor anti-pattern and not really what I was looking for.

Best Answer

If all you want to do is create class X with certain arguments, subclassing is an odd way of expressing that intent, because you aren't using any of the features that classes and inheritance give you. It's not really an anti-pattern, it's just strange and a bit pointless (unless you have some other reasons for it). A more natural way of expressing this intent would be a Factory Method, which in this case is a fancy name for your "helper method."

Regarding the general intuition, both "more specific" and "a limited range" are potentially harmful ways of thinking about subclasses, because they both imply that making Square a subclass of Rectangle is a good idea. Without relying on something formal like LSP, I would say a better intuition is that a subclass either provides an implementation of the base interface, or extends the interface to add some new functionality.