Sunday, May 9, 2010

Construction Interfaces - Why We Need Them

Most object-oriented languages have a concept of an interface - the contract for a type, usually a class, that defines it's public operations i.e. behavior.

But not all of them have the ability to define the construction interface. How do I define the construction interface? Construction interface is a contract that specifies how an object can be constructed.

Object construction is as essential to the object-oriented paradigm as are other tenets such as polymorphism or inheritance. Object construction defines constraints on an object-oriented model that better describe the objects involved. It adds semantics to the object life-cycle. For instance, who can create some object and how?

Take C#, for example. How would you express the following in C#: object Car can only be constructed with a collection of CarParts. It sounds reasonable, doesn't it. Why wouldn't I be able to say that some object can only be constructed out of some other object? The closest I can get to it in C# is to define something like this:

public interface ICarFactory {
    ICar Create( IEnumerable< ICarPart > parts );
}
So, I would define a factory object for a Car and that factory object is responsible for constructing my Car objects, and it has a strict interface that defines that a Car object can only be constructed out of CarParts. OK, so far so good. It seems like there's a solution. It's not great, though. What if I don't know about the CarFactory, what if someone passes me the Car object and I have no idea how it was constructed? How can I be sure it was constructed out of CarParts? The factory interface doesn't really put any constraints on the implementation of the Car, only the implementation of the Car factory. The only thing restricting the construction of the implementation of Car is its class constructor, but there's no interface for it, is there?

The construction interface is essential to being able to define object dependencies in a type strict manner. Say object A depends on object B, object B on object C. There's no way to define the constraint that the dependency chain needs to be satisfied on object construction.

Syntax for defining a construction interface could be something like this:

public interface ICar {
    Constructor( IEnumerable< ICarPart > parts );
}

This would require that every type that implements ICar has to have a public constructor that takes a collection of car parts. No need for a factory anymore. Furthermore, I could use the ICar interface as a generic type parameter constraint for a generic method or class and call that constructor from it because it's guaranteed to exist.

Now, if only the guys in Redmond could read this.

4 comments:

  1. I know this problem and it's a pain. The problem is that interfaces and object state do not go well with each other. Interfaces are meant to be behavioural contracts that types can implement to declare that they adhere to such contract, without making any assumptions about their state.

    I think what you really need is an abstract base class as opposed to an interface. There is nothing wrong with abstract base classes, yet I see some want to have a pure interface-oriented design for exposing their domains. Admittedly interfaces may be a tad faster than abstract base classes, but if you keep your base class purely abstract (i.e. no virtual methods) it should be almost as fast as an interface.

    With abstract base classes you can specify a non-default constructor. Then derived objects are forced to call that constructor, and you are guaranteed that your dependencies have been passed to the object.

    ReplyDelete
  2. Yes, abstract base class does put that constraint on all objects derived from it. I see a few problems with this approach. Not every object that implements the interface has to derive from that base class so simply having an object doesn't tell you anything about how it's constructed. Furthermore, base classes introduce tight coupling and are rightfully considered too invasive. Not to mention the limitation that you can only derive from one class which would limit the design somewhat.

    ReplyDelete
  3. There are certainly trade offs when using abstract base classes such as single inheritance, but I question the need to derive from multiple classes in most cases. Single responsibility, remember?

    I think as a general rule, interfaces define public interactive contracts and abstract classes help define even more, including implementation. I lean less toward changing the nature of interfaces for object construction details.

    ReplyDelete
  4. I generally agree with your point about interfaces, but the fact remains that the only way to specify the contract for dependencies of an object is its constructor which promotes tight coupling of implementations.

    ReplyDelete