FeatureDef
FeatureDef Objects - An Extensible "Aspect Language"
Most AOP systems include one or more "aspect languages". These are little (or sometimes not so little) languages used to describe some aspect of a system (see IntroToAOP for an explanation of "aspects"). For example, the ZPatterns? system has an aspect language called "SkinScript?", which is used to specify data storage and transactional behavior in ZPatterns applications.
The advantage of these specialized languages is that they are compact and precise, but the disadvantage is that they are another language you have to learn, and you can only use the languages or features that are built in. TransWarp takes a different approach, by using Python objects as its aspect language. Instead of defining a feature using a statement in a specialized language, you place a "FeatureDef" object (one which implements the FeatureWeaving interface) in an aspect or one of its nested classes. At WeavingTime?, the FeatureDef is given an opportunity to participate in the creation of the component class created from the source aspects. Example:
from TW.Aspects import Aspect from TW.Features import FeatureExpression from whrandom import randint class DiceService(Aspect): class RandomValueFeature: def __init__(self,lo,hi): self.lo = lo self.hi = hi def next(self): print "Rolling from",self.lo,"to",self.hi return randint(self.lo,self.hi) class DiceElement: diceValue = FeatureExpression('RandomValueFeature(1,6)') def roll(self): return self.diceValue.next() def getDice(self): return self.DiceElement()
In the above example, FeatureExpression
is a FeatureDef class that creates an attribute of a class at WeavingTime?. In this case, an instance of RandomValueFeature
will be created and placed in the output class's dictionary. (We cannot simply place an instance of RandomValueFeature
directly in the class, because there would then be no opportunity to weave aspects into the RandomValueFeature
class at WeavingTime?.)
Because FeatureDefs participate in the weaving process, they can be written to do almost anything to the output component. They can simply insert something into the output class(es), or they may modify the things that are there. They can define rules for combining class attributes between layered aspects, so for example you could create a "MethodChain?" FeatureDef that allowed methods defined in different aspects to be chained or wrapped around each other. Or, you could create a "AppendedSequence?" FeatureDef that would add together each aspect's __implements__
attribute to create one long sequence in the output class.
TransWarp's TW.Features
module implements various standard FeatureDefs which may be used in your programs. Some of these are automatically used for you, if you do not manually specify them. Specifically, TransWarp uses a ClassFeature? FeatureDef to produce nested classes or aspects in an aspect being woven, and all other features default to using the OverwriteFeature FeatureDef. So even these seemingly "built-in" rules are implemented using FeatureDefs and can be overridden if desired. A keyword argument can even be passed in at WeavingTime? to replace the function normally used to supply these default FeatureDefs.
So, to sum up, FeatureDefs are a way of creating as many aspect languages as you care to, in the form of object libraries rather than as actual languages. And these "languages" have full access to the generated components, so you're free to create whatever kinds of generation tools you might need or want.