Tuesday, May 15, 2012

CLOS Class Naming

The classes of the Common Lisp spec, the MOP and big CLOS projects like CLIM use some naming conventions which may not make sense at first. I'm speaking of the STANDARD- and BASIC- prefixes. What is the idea behind them?

Protocol Oriented Programming

In CLOS one defines "protocols" using classes and generic functions. Remember: Methods do belong to generic functions and not to classes. There are no dedicated means to define protocols - it is idiomatic. A common practice is to define "protocol classes" which often do not have any slots at all. They serve as superclasses to all classes which implement the protocol.

Basics and Standards

In the set of protocol implementation classes there may be one, which contains a minimal complete implementation and/or there might be one which is something like the default implementation. Assuming a protocol for FOOBAR defined through the protocol-class FOOBAR the minimal implementation could be called BASIC-FOOBAR and the default one STANDARD-FOOBAR. The BASIC-** one if often called FUNDAMENTAL-** too.

Extensibility

It is often a good idea to implement STANDARD-** by inheriting the BASIC-** implementation, overriding the necessary parts. A protocol user who wants to implement his own implementation can decide on which level he wants to get in: He could inherit from STANDARD-** if his implementations is only a small variant. He may inherit from BASIC-** if the implementation is more complicated and perhaps incompatible to what STANDARD-** does. If even BASIC-** is to strict, he could try to implement the protocol class completely on its own - but this is then more like implementing interfaces in classical object oriented languages, where you cannot inherit behaviour at all. You have to provide methods for any necessary generic function the protocol is made of. This is the most work and implementing a protocol is often more than just following the interfaces.

2 comments:

  1. "If even BASIC-** is to strict, he could try to implement the protocol class completely on its own - but this is then more like implementing interfaces in classical object oriented languages, where you cannot inherit behaviour at all. You have to provide methods for any necessary generic function the protocol is made of. This is the most work and implementing a protocol is often more than just following the interfaces."

    Mixins can help with that; they're much more useful in this protocol-oriented approach than the "base-class" approach.

    I like to have various mixins providing "standard" implementations of focussed aspects of the implementation, and then having STANDARD-FOOBAR being little more than an aggregation of mixins. This gives even more flexibility and convenience, as well as making you think more deeply about the protocol (especially questioning your basic assumptions, where to "draw the line" with respect to what will be easy or possible to do and what's out of scope), resulting in a better design, in my experience.

    ReplyDelete
    Replies
    1. You're absolutely right, but mixins are somewhat orthogonal to this topic. I'm using them too. Class definitions in Common Lisp are often just only done for their superclasses list. I've learned a lot about that when designing MEL-BASE and its different protocols.

      While using mixins is a good idea, I find it important though to provide different levels of extensibility using this "fundamental" vs "standard" layering. The base class approach is the best for a simple "just use" layer of the extensibility interface. Mixins are a toolbox for experts. So to combine the best of both world means structuring your protocol implementations using mixins and define the extension layers using them.

      Delete