January 28, 2008

  • Policy-Based class design

    Lately I have become really interested in Policy-Based class design. You can blame Andrei Alexandrescu and his book, “Modern C++ Design: Generic Programming and Design Patterns Applied”. It is a pretty awesome book, whether you are a C++ programmer or not. It gives some great insight into some new design patterns that you can not only use in place of traditional OOP design patterns, but can use to augment them.

    Using traditional OO, if I was creating a SocketLibrary, I could create a class heirarchy that had SingleThreadedSocket, MultiThreadedSocket, AsyncSocket concrete classes. But then say the client of my socket classes wanted to be able to use different buffering techniques for the underlying os sockets. All of a sudden I could have SingleThreadedBufferedSocket, SingleThreadedNonBufferedSocket, MultiThreadedBufferedSocket, etc…

    I have run into this problem with traditional OO programming so many times in my programming job here at xanga. There ends up being one part of the class I want to change, but it is somewhere up in the class hierarchy, so I have to pollute the hierarchy with an override for that functionality. Before you know it, libraries are overly complex, programmers are using the wrong classes, and the probability for mistake rises dramatically.

    Andrei’s solution: Policy-Based class design. Here is a brief rundown of Policy-Based class design taken from the book: “In brief, policy-based class design fosters assembling a class with complex behavior out of many little classes, each of which takes care of only one behavioral or structural aspect.” Basically, you can construct your classes to be nothing more than containers for policies, and use the C++ templating engine to pass different policy classes to your container. This forces the designer to think more in terms of decomposing a class into little pieces that a client may want to override, creating policies that most programmers will use by default, but allowing the simple overriding of almost any aspect of the class.

    I’ll finish here with an example of a simple policy based class. Say I have a factory of widgets, and I wanted to move how the creation of those widgets is done into a policy.

    template <class T>
    struct OpNewCreator
    {
       static T* Create()
       {
          return new T;
       }
    };

    template <class T>
    struct MallocCreator
    {
       static T* Create()
       {
          void* buf = std::malloc(sizeof(T));
          if (!buf) return 0;
          return new(buf) T;
       }
    };

    template <typename CreationPolicy>
    class WidgetFactory : public CreationPolicy
    {
      …
    };

    As a user of this library, I can say:

    WidgetFactory<MallocCreator<Widget> > myFactory;

    Now, whenever WidgetFactory needs to create the object, it will just call the Create() function. If i want my own policy, I can create it and pass it in as the template parameter.

    The code might look a little funky, but the book discusses many techniques for making the library syntax much cleaner. I don’t want to duplicate all of his ideas here, so if you are interested, buy his book.

Comments (14)

  • By looking at the title, I thought this post would be on education  Not that I am disappointed, malloc is pretty interesting too. 

  • Malloc is evil heh :p  This looks a lot like the Strategy OOP pattern, where your function is wrapped by an object that can be swapped at runtime when you want to use a different implementation of the function.

  • @patrick -

    Good catch Patrick! That is true, policy based class design is very
    similar to the Strategy OOP pattern, with the added benefit that it is
    compile time bound. This allows clients to submit enriched policies
    that add extra functionality to a class that will be typesafe.

    Another benefit somewhat related is the host class can even define
    optional functionality, because the compiler doesn’t instantiate member
    functions if they are never used. If the host class knows that some
    policies will have certain abilities, it can wrap those abilities in a
    member function. If someone instantiates an object with those
    particular policies, they can use the function. If they instantiate an
    object with a policy that doesn’t support that particular ability, and
    they try to use it, the compiler will tell them where the bug is.

  • @patrick -

    Correct me if I’m wrong here. To put it more simply, with the strategy
    pattern clients of the library would still be tied to using an
    interface, which might have to be changed to fit their needs.

  • @adam - I believe that is the case.  The strategy pattern necessitates that all strategies be expressible within the same interface.  There is; however, nothing to prevent a class employing the strategy pattern on multiple dimensions.  Furthermore, by allowing its strategies to extend their own interfaces and for the strategies to get references to one another; introspection from one strategy into another will allow OO systems to be capable of expressing similar behavior to policy-based designs.  I would argue still that the policy-based designs express this more elegantly.

  • @Michael - 

    If the holder class has to be assigned the interface in advance, how would you do the equivalent of using an “enriched policy” that extends the interface of the holder class?

  • @adam -

    I just looked up policy-based design on wikipedia and it said that it has been described as “a compile-time variant of the strategy pattern,” which is basically the same conclusion we came to.  I looked at the strategy pattern again and confirmed that its intended usage is algorithm selection, as opposed to changing the implementation of an entire interface (which really could just be referred to as class inheritance in general).

  • every time you post something like this, I’m reminded that I’m not as much a programmer as I am an applier of software glue.

  • @sean - 

    How do you know we aren’t just pretending to be programmers with a “fancy technical word generator”?

  • @adam - hey adam, this is the real sean… sorry about that, my “whiney inferiority complex rant generator” took off on its own!

  • @sean -

    That’ll learn you to use the non-standard MS implementation of WICRG Script

  • Huh.  I vaguely remember something called component oriented programming that had a similar premise.  This related?

  • @joseph - 

    I don’t believe so Joe. I found this link on component oriented programming: http://www.ccs.neu.edu/home/lorenz/oopsla2001/23_Frohlich.pdf

    Looks interesting, I’ll have to dive into it more. It appears at first glance to have more of an emphasis on being distributed, which in itself is a very generalized word.

  • Its neat!! I think computers are neat!!! *hides behind macbook*

Post a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *