Tuesday, August 26, 2008

The art of delegation

Delegation seems like a pretty simple concept. That is, why should it be considered an art? Well, there is a fine balance between having a proper distribution of responsibilities and having operations that try to accomplish everything under the sun. A common delegation use is the pure fabrication design pattern. Pure fabrication should be introduced when there no logical way to distribute the responsibilities among a society of classes.

For example, lets examine the following class implementation:

class BlogEntry:
def __init__(self, *args, **kw):
if kw.has_key('title') and kw['title']:
self.title=kw['title']
else:
self.title=None
if kw.has_key('body') and kw['body']:
self.body=kw['body']
else:
self.body=None
if kw.has_key('date') and kw['date']:
self.date=kw['date']
else:
self.date=None
Now, this constructor looks pretty straight forward. We have three attributes to initialize; title, body, and date. There is a pattern here. Each attribute initialization is four lines of code long, the only difference being the name of the attribute. It seems that we could pass the responsibility of initializing keyword parameters to another party. One that is better at the task. Blog entries are good at representing the blog entry. The blog entry class wasn't designed with Python dictionary processing in mind.

Here is another class implementation we can introduce in order to offload some of the responsibilities.

class BlogEntryTools:
@classmethod
def init_param(cls, name, kw):
if kw.has_key(name) and kw[name]:
return kw[name]

@classmethod
def init_title(cls, kw):
return cls.init_param('title', kw)

@classmethod
def init_body(cls, kw):
return cls.init_param('body', kw)

@classmethod
def init_date(cls, kw):
return cls.init_param('date', kw)

Using this new utility class, we can now better distribute the responsibilities throughout our code. To complete the picture, here is our new implementation of BlogEntry. The constructor is much more elegant and maintainable at a very low cost.

class BlogEntry:
def __init__(self, *args, **kw):
self.title=BlogEntryTools.init_title(kw)
self.body=BlogEntryTools.init_body(kw)
self.date=BlogEntryTools.init_date(kw)