Article Discussion
Scala's Stackable Trait Pattern
Summary: This article describes a Scala design pattern in which traits provide stackable modifications to underlying core classes or traits.
6 posts.
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: September 26, 2011 8:35 AM by Christian
    Bill
     
    Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
    Scala's Stackable Trait Pattern
    September 29, 2009 9:00 PM      
    This article describes a Scala design pattern in which traits provide stackable modifications to underlying core classes or traits:

    http://www.artima.com/scalazine/articles/stackable_trait_pattern.html

    What do you think of the Stackable Trait pattern?
    • Howard
       
      Posts: 25 / Nickname: hlovatt / Registered: March 3, 2003 1:20 PM
      Re: Scala's Stackable Trait Pattern
      September 30, 2009 10:45 PM      
      Bill,

      Nicely written article. The Trait form is a nice alternative to decorators, I guess it has the disadvantage that if people do a lot of:

      val queue = new BaseIntQueue with Filter
      


      Then you will create a lot of classes unnecessarily. The decorator equivalent doesn't create the extra classes.

      One thing that I don't like about either the decorator or trait version is the order dependence, it is far to easy to write (or edit in when maintaining a program):

      val queue = new BaseIntQueue with Filter with Double
      


      When you intended:

      val queue = new BaseIntQueue with Double with Filter
      
    • John
       
      Posts: 62 / Nickname: zbo / Registered: January 20, 2007 9:22 AM
      Re: Scala's Stackable Trait Pattern
      September 30, 2009 10:18 AM      
      > This pattern is similar in structure to the decorator
      > pattern, except it involves decoration for the purpose of
      > class composition instead of object composition. Stackable
      > traits decorate the core traits at compile time, similar to
      > the way decorator objects modify core objects at run time
      > in the decorator pattern.

      This is somewhat incorrect. Role analysis is actually meant to unify object-based and class-based methods for decribing patterns of interactions between objects.

      This idea just hasn't been mathematically formalized (that I know of). The closest formalization was done by one of Trygve's Ph.D. students in the '90s.
      • Bill
         
        Posts: 409 / Nickname: bv / Registered: January 17, 2002 4:28 PM
        Re: Scala's Stackable Trait Pattern
        September 30, 2009 10:53 AM      
        Hi John,

        > > class composition instead of object composition.
        > Stackable
        > > traits decorate the core traits at compile time, similar
        > to
        > > the way decorator objects modify core objects at run
        > time
        > > in the decorator pattern.
        >
        > This is somewhat incorrect. Role analysis is actually
        > meant to unify object-based and class-based methods for
        > decribing patterns of interactions between objects.
        >
        Can you elaborate? I'm not sure what your saying is somewhat incorrect.

        My goal was to preempt folks from concluding that this is just decorator, because the GoF book makes it clear that the intent of decorator is (quoting the book) to:

        Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

        Whereas this is an example of "subclassing to extend functionality" really, and it isn't dynamic. What's new is Scala's notion of delayed binding of the meaning of super, abstract override, and linearization, which didn't exist when the GoF book was written. The decorator pattern looks in Scala pretty much the same as it does in Java. So even though this has a similar structure to decorator, is a similar concept, it really is different from decorator, because it is a static, compile-time thing.
        • John
           
          Posts: 62 / Nickname: zbo / Registered: January 20, 2007 9:22 AM
          Re: Scala's Stackable Trait Pattern
          October 7, 2009 7:07 AM      
          > Hi John,
          >
          > > > class composition instead of object composition.
          > > Stackable
          > > > traits decorate the core traits at compile time,
          > similar
          > > to
          > > > the way decorator objects modify core objects at run
          > > time
          > > > in the decorator pattern.
          > >
          > > This is somewhat incorrect. Role analysis is actually
          > > meant to unify object-based and class-based methods for
          > > decribing patterns of interactions between objects.
          > >
          > Can you elaborate? I'm not sure what your saying is
          > somewhat incorrect.
          >
          > My goal was to preempt folks from concluding that this is
          > just decorator, because the GoF book makes it clear that
          > the intent of decorator is (quoting the book) to:
          >
          > Attach additional responsibilities to an object
          > dynamically. Decorators provide a flexible alternative to
          > subclassing for extending functionality.
          >
          > Whereas this is an example of "subclassing to extend
          > functionality" really, and it isn't dynamic. What's new is
          > Scala's notion of delayed binding of the meaning of super,
          > abstract override, and linearization, which didn't exist
          > when the GoF book was written. The decorator pattern looks
          > in Scala pretty much the same as it does in Java. So even
          > though this has a similar structure to decorator, is a
          > similar concept, it really is different from decorator,
          > because it is a static, compile-time thing.

          Hi Bill,

          I am referring to the symmetry between the GoF Decorator pattern GoF State pattern (which Trygve essentially wrote an entire book about, as well as an object-oriented software method for). The GoF State pattern in the book is described as a behavioral pattern, but its more structural in nature: the focus, as in Trygve's OOram (his software method), is about defining the context in which a behavior is applicable. Within that context, you are modeling the structure of object interactions. GoF sees it as a behavioral pattern mainly because their implementation is synchronous with its environment; each role knows where to migrate the token to next. In an asynchronous environment, the pattern is purely structural in nature because the objects communicate by message-passing and state transitions are triggered by signals.

          Traits allow you to more easily specify contracts for what sort of compositions an object allows.

          As I said, role analysis is actually meant to unify object-based and class-based methods for describing patterns of interactions between objects (this is almost a word for word quote from Trygve). Most of the examples in Trygve's book Working with Objects is dedicated to this idea. The only unfortunate thing is Trygve doesn't really discuss "dependency injection" in conjunction with that big picture idea, so the reader likely does not see the "big idea".

          > Whereas this is an example of "subclassing to extend
          > functionality" really,

          As you subclass to extend functionality, you are changing the problem domain. This is mainly due to the fact that in your example you are not using scala's features to encapsulate some problem domain but rather demonstrate some wiring pattern. The wiring pattern is a code reuse facility with excellent type safety, but it is a clumsy way to package a problem domain.

          > and it isn't dynamic.

          To wit, I would argue asynchronous message-passing is dynamic, whereas hardwiring sequences of collaborations is static.

          The hard problem to solve in OO is not structural. OO applications are filled with structural features. The hard part is to specify at the language level your object interactions (use cases).
          • John
             
            Posts: 62 / Nickname: zbo / Registered: January 20, 2007 9:22 AM
            Re: Scala's Stackable Trait Pattern
            October 12, 2009 7:34 AM      
            Bill,

            did that make any sense?

            Basically, a GoF decorator pattern allows you to dynamically assign responsibilities to an object or class, whereas a GoF State pattern simply associates roles within a context to a behavior responsibility. Looking at it this way, the only difference between the two patterns is a concrete notion of "when".

            In Python, a "decorator" actually is determined at "compile-time" ("when" the AST is converted into a byte code stream) and so the blurriness of these two patterns is perhaps best seen in this language. One huge difference is syntax and how things are composed at "code-write-time". However, ultimately, at run-time, the code is representing some problem domain.

            Just as a role does not necessarily need to know what the next role transition will be, so too a decorator does not need to know what other decorators are applied. To each decorator, it is the same object. And from the point-of-view of the decorated object, these decorations do not even exist. Likewise, in an State pattern, the object's chief knowledge responsibility is the context (current role) with regards to its collaboration with other objects -- the object shouldn't care about details such as "how" a message is processed in a role.
    • Christian
       
      Posts: 1 / Nickname: 78559 / Registered: September 9, 2011 6:59 AM
      Re: Scala's Stackable Trait Pattern
      September 26, 2011 8:35 AM      
      I wonder why it is required to say


      trait Doubling extends IntQueue {
      abstract override def put(x: Int) { super.put(2 * x) }
      }


      instead of just


      trait Doubling extends IntQueue {
      override def put(x: Int) { super.put(2 * x) }
      }


      The first syntax looks really odd, because you are actually defining a method, not just declaring it. Also, Scala is advertised to be concise, and this looks just superfluous.