Thursday, April 17, 2008

Attribute-based Interface Design in Python

The core concept of Cheriton's programming methodology is "Attribute-based Interface Design." The functionality of an interface can only be accessed by reading or writing its attributes. Thus, instead of verb-like calls named "SetWindowTitle" or "TurnOnHilite, you would have "windowTitleIs" and "hiliteIs". Furthermore, objects are only created, accessed, and deleted through a manager.

Let's see a quick example of this approach in Python:

"""
instance.py

The Instance and InstanceManager provide the basics for an Attribute-based Interface.
All access to the interface's functionality are through an Instance object's
attribute methods. All calls to create, retrieve, or delete Instances are through an
InstanceManager. Subclassed instances of Instance and Instance::Manager handle the
implementation.

This approach ensures a strict division between the interface and its implementation,
plus consistent naming and architecture conventions. It distills functionality to
a group of attributes and their settings.

The Attribute-based Interface is part of a methodology created by Prof. David Cheriton
of Stanford in his course CS249, Object-Oriented Programming from a Modeling and Simulation
Perspective. See http://www.stanford.edu/class/cs249a/. This is my version of
Prof. Cheriton's methodology in Python and may differ from his ideas and his intent.

Jack Trainor 2008
"""

class Instance(object):
def __init__(self, _name, _type, _manager):
pass

def name(self):
return None

def type(self):
return None

def manager(self):
return None

def attribute(self, attrName):
return None

def attributeIs(self, attrName, attrVal):
pass

class Manager(object):
def instanceNew(self, _name, _type):
return None

def instance(self, _name):
return None

def instanceDel(self, _name):
pass

def InstanceManager():
import instanceimpl
return instanceimpl.ManagerImpl()

def test():
mgr = InstanceManager()
airport = mgr.instanceNew("SFO", "Airport")
airport.attributeIs("city", "San Francisco")
print airport.type(), airport.name(), airport.attribute("city")

ticket = mgr.instanceNew("T-12345", "Ticket")
ticket.attributeIs("destination", "Boston")
print ticket.type(), ticket.name(), ticket.attribute("destination")

if __name__ == "__main__":
test()

And here's the implementation for Instance that does the work for the calls in test(). Download load instance.py and instanceimpl.py and run instance.py to see this approach at work.

"""
instanceimpl.py

This file provides the beginnings of an implementation for an attribute-based interface.
It is quite simple and contains no error-checking or exception-handling.
"""
import instance

class InstanceImpl(instance.Instance):
def __init__(self, _name, _type, _manager):
self.name_ = _name
self.type_ = _type
self.manager_ = _manager
self.attribute_ = {}

def name(self):
return self.name_

def type(self):
return self.type_

def manager(self):
return self.manager_

class Airport(InstanceImpl):
def attribute(self, attrName):
if attrName == "city":
return self.attribute_.get(attrName, "")
return ""

def attributeIs(self, attrName, attrVal):
if attrVal != self.attribute(attrName):
if attrName == "city":
self.attribute_[attrName] = attrVal

class Ticket(InstanceImpl):
def attribute(self, attrName):
if attrName == "destination":
return self.attribute_.get(attrName, "")
return ""

def attributeIs(self, attrName, attrVal):
if attrVal != self.attribute(attrName):
if attrName == "destination":
self.attribute_[attrName] = attrVal

class ManagerImpl(instance.Instance.Manager):
def __init__(self):
self.instance_ = {}

def instanceNew(self, _name, _type):
_instance = None
if _type == "Airport":
_instance = Airport(_name, _type, self)
elif _type == "Ticket":
_instance = Ticket(_name, _type, self)
if _instance:
self.instance_[_name] = _instance
return _instance

def instance(self, _name):
return self.instance_[_name]

def instanceDel(self, _name):
del self.instance_[name]

No comments: