Recently I have been exploring Reg, a library inspired by zope.component written by Faassen, and I found its simplification of ZCA to be pretty interesting. Being really loving ZCA for a while now, I end up trying to figure out how the ZCA patterns fits if I were to use Reg in my future projects. So here are the list of items I discovered so far:
Adapters
This is the most common pattern I use with ZCA, primarily to simplify writing logic by standardizing the interface of objects I work with into a common set of behavior/functions:
In ZCA , adapters are done this way:
And that is quite a code, which utilizes classes, and large external interfaces libraries and component libraries which might can make many pythonistas cringe.
In Reg, things are simplified. Similar functionality is done not through interfaces and complex object/class markers, but through simple functions. Reg adapter interfaces are simply functions:
Adapters
This is the most common pattern I use with ZCA, primarily to simplify writing logic by standardizing the interface of objects I work with into a common set of behavior/functions:
In ZCA , adapters are done this way:
from zope import interface
from zope import component
class IDog(interface.Interface):
def bark():
pass
class Dog(object):
interface.implements(IDog)
def bark(self):
return 'Woof'
class IDuck(interface.Interface):
def quack():
pass
class Duck(object):
interface.implements(IDuck)
def quack(self):
return 'Quack'
class IAnimalSoundAdapter(interface.Interface):
def make_sound():
pass
class DogSoundAdapter(grok.Adapter):
interface.implements(IAnimalAdapter)
interface.adapts(IDog)
def __init__(self, dog):
self._dog = dog
def make_sound(self):
return self._dog.bark()
class DuckSoundAdapter(grok.Adapter):
interface.implements(IAnimalSoundAdapter)
interface.adapts(IDuck)
def __init__(self, duck):
self._duck = duck
def make_sound(self):
return self._duck.quack()
gsm = component.getGlobalSiteManager()
gsm.registerAdapter(DogSoundAdapter, (IDog,), IAnimalSoundAdapter)
gsm.registerAdapter(DuckSoundAdapter, (IDuck,), IAnimalSoundAdapter)
dog = Dog()
duck = Duck()
dog.bark() # Woof
duck.quack() # Quack
IAnimalSoundAdapter(dog).make_sound() # Woof
IAnimalSoundAdapter(duck).make_sound() # Quack
And that is quite a code, which utilizes classes, and large external interfaces libraries and component libraries which might can make many pythonistas cringe.
In Reg, things are simplified. Similar functionality is done not through interfaces and complex object/class markers, but through simple functions. Reg adapter interfaces are simply functions:
import reg
import reg.implicit
class Dog(object):
def bark(self):
return 'Woof'
class Duck(object):
def quack(self):
return 'Quack'
@reg.generic
def make_sound(obj):
raise NotImplementedError
def dog_sound(dog):
return dog.bark()
def duck_sound(duck):
return duck.quack()
registry = reg.Registry()
reg.implicit.initialize(registry)
registry.register(make_sound, [Dog], dog_sound)
registry.register(make_sound, [Duck], duck_sound)
dog = Dog()
duck = Duck()
make_sound(dog) # Woof
make_sound(duck) # Quack
Now, ZCA users might shout by now, "I want class based adapters!" (I know I did). This is how it can be implemented in Reg:
import reg
import reg.implicit
class Dog(object):
def bark(self):
return 'Woof'
class Duck(object):
def quack(self):
return 'Quack'
@reg.generic
def animal_sound_adapter(obj):
raise NotImplementedError
class DogSoundAdapter(object):
def __init__(self, dog):
self._dog = dog
def make_sound(self):
return self._dog.bark()
class DuckSoundAdapter(object):
def __init__(self, duck):
self._duck = duck
def make_sound(self):
return self._duck.quack()
registry = reg.Registry()
reg.implicit.initialize(registry)
registry.register(animal_sound_adapter, [Dog], DogSoundAdapter)
registry.register(animal_sound_adapter, [Duck], DuckSoundAdapter)
dog = Dog()
duck = Duck()
animal_sound_adapter(dog).make_sound() # Woof
animal_sound_adapter(duck).make_sound() # Quack
Thats it for now, next one I will probably share about multiadapters on Reg.