In any sufficiently-sized application or framework, it's common to end up lumping a lot of different concerns into the same class. For example, you may have persistence code, business logic and UI all jammed into a single class. Attribute and method names for all sorts of different operations get shoved into a single namespace -- even when using mixin classes.
Separating concerns into different objects, however, makes it easier to write reusable and separately-testable components. The AddOns package (peak.util.addons) lets you manage concerns using AddOn classes.
AddOn classes are like dynamic mixins, but with their own private attribute and method namespaces. A concern implemented using add-ons can be added at runtime to any object that either has a writable __dict__ attribute, or is weak-referenceable.
AddOn classes are also like adapters, but rather than creating a new instance each time you ask for one, an existing instance is returned if possible. In this way, add-ons can keep track of ongoing state. For example, a Persistence add-on might keep track of whether its subject has been saved to disk yet:
>>> from peak.util.addons import AddOn
>>> class Persistence(AddOn):
... saved = True
... def changed(self):
... self.saved = False
... def save_if_needed(self):
... if not self.saved:
... print "saving"
... self.saved = True
>>> class Thing: pass
>>> aThing = Thing()
>>> Persistence(aThing).save_if_needed() # no action taken
This makes it easy for us to, for example, write a loop that saves a bunch of objects, because we don't need to concern ourselves with initializing the state of the persistence add-on. A class doesn't need to inherit from a special base in order to be able to have this state tracked, and it doesn't need to know how to initialize it, either.
Of course, in the case of persistence, a class does need to know when to call the persistence methods, to indicate changedness and to request saving. However, a library providing such an add-on can also provide decorators and other tools to make this easier, while still remaining largely independent of the objects involved.
Indeed, the AddOns library was actually created to make it easier to implement functionality using function or method decorators. For example, one can create a @synchronized decorator that safely locks an object -- see the example below under Threading Concerns.
In summary, the AddOns library provides you with a basic form of AOP, that lets you attach (or "introduce", in AspectJ terminology) additional attributes and methods to an object, using a private namespace. (If you also want to do AspectJ-style "advice", the PEAK-Rules package can be used to do "before", "after", and "around" advice in combination with add-ons.)