34 votes

But des interfaces Zope?

J'ai commencé à utiliser Zope interfaces dans mon code, et maintenant, ils sont en réalité que de la documentation. - Je les utiliser pour spécifier quels sont les attributs de la classe devrait posséder, de les implémenter explicitement dans les classes appropriées et explicitement vérifier où j'en attends. C'est très bien, mais je tiens à en faire plus si possible, comme le fait de vérifier que la classe a mis en œuvre l'interface, au lieu de simplement vérifier que j'ai dit que la classe implémente l'interface. J'ai lu le zope wiki une couple de fois, mais ne peut toujours pas voir beaucoup plus d'utilisation pour les interfaces de ce que je suis en train de faire. Donc, ma question est à quoi d'autre pouvez-vous utiliser ces interfaces, et comment les utilisez-vous pour plus.

52voto

Richard Barrell Points 1952

Là où je travaille, nous utilisons des Interfaces de sorte que nous pouvons utiliser à la ZCA, ou l' Architecture de Composants de Zope, qui est un ensemble de cadre pour la fabrication de composants sont remplaçables et enfichables à l'aide d' Interfaces. Nous utilisons la ZCA, de sorte que nous pouvons faire face à toutes sortes de client par client personnalisation, sans nécessairement avoir à fourche de notre logiciel ou avez toutes les nombreuses par client bits gâcher l'arbre principal. Le Zope wiki est souvent assez incomplet, malheureusement. Il y a un bon-mais-laconique explication de la plupart de la ZCA de fonctionnalités sur son ZCA du pypi page.

Je n'utilise pas d' Interfaces pour rien, comme vérifier qu'une classe implémente toutes les méthodes pour un Interface. En théorie, cela peut être utile lorsque vous ajoutez une autre méthode d'une interface, pour vérifier que vous avez rappelé à ajouter la nouvelle méthode pour toutes les classes qui implémentent l'interface. Personnellement, je préfère largement à créer un nouveau Interface sur la modification d'une ancienne. La modification de vieux - Interfaces est généralement une très mauvaise idée une fois qu'ils sont dans les œufs qui ont été mis sur pypi ou pour le reste de votre organisation.

Une petite remarque sur la terminologie: les classes implémentent Interfaces, et les objets (instances de classes) fournissent Interfaces. Si vous voulez vérifier une Interface, il faudrait écrire ISomething.implementedBy(SomeClass) ou ISomething.providedBy(some_object).

Donc, jusqu'à des exemples de cas où la ZCA est utile. Imaginons que nous sommes en train d'écrire un blog, à l'aide de la ZCA pour le rendre modulaire. Nous allons avoir un BlogPost objet pour chaque poste, qui sera l' IBlogPost interface, tous définis dans notre pratique-dandy my.blog d'œufs. Nous allons également stocker le blog de la configuration en BlogConfiguration objets qui fournissent IBlogConfiguration. L'utilisation de ce comme un point de départ, nous pouvons mettre en œuvre de nouvelles fonctionnalités, sans nécessairement avoir à toucher my.blog à tous.

Ce qui suit est une liste d'exemples de choses que l'on peut faire à l'aide de la ZCA, sans avoir à modifier la base my.blog d'œufs. Je ou mes collègues l'ont fait toutes ces choses (et il l'a trouvé utile) sur le réel pour des projets du client, si nous n'étions pas à la mise en œuvre de blogs à l'époque. :) Certains des cas d'utilisation ici pourrait être mieux résolus par d'autres moyens, tels que l'impression d'un fichier CSS.

  1. Ajout de points de vue (BrowserViews, généralement enregistrés dans ZCML avec l' browser:page "directive") à tous les objets qui fournissent IBlogPost. Je pourrais faire un my.blog.printable d'œufs. Qui de l'oeuf serait inscrire un BrowserView appelés print pour IBlogPost, ce qui rend le post de blog par le biais d'un Zope Page Modèle conçu pour produire le HTML qui imprime bien. Qu' BrowserView apparaît ensuite à l'URL /path/to/blogpost/@@print.

  2. L'inscription à l'événement mécanisme de Zope. Dire que je veux publier des flux RSS, et je tiens à les générer à l'avance, plutôt que sur demande. Je pourrais créer un my.blog.rss d'œufs. Dans l'oeuf, je voudrais enregistrer un abonnement pour des événements qui fournissent IObjectModified (zope.lifecycleevent.interfaces.IObjectModified), sur des objets qui fournissent IBlogPost. Que les abonnés obtenir appelée à chaque fois qu'un attribut modifié sur quoi que ce soit en fournissant IBlogPost, et je pourrais l'utiliser pour mettre à jour tous les flux RSS que le blog devrait apparaître.

    Dans ce cas, il peut être préférable d'avoir un IBlogPostModified événement qui est envoyé à la fin de chacun des BrowserViews que de modifier les messages de blog, depuis IObjectModified est envoyé une fois sur chaque attribut changement qui pourrait être trop souvent pour des raisons de performances.

  3. Les adaptateurs. Les adaptateurs sont en fait des "jette" à partir d'une Interface à une autre. Pour la programmation, le langage des geeks: Zope adaptateurs de mettre en œuvre "ouverte" multiple à répartition en Python (par "ouvrir", je veux dire ", vous pouvez ajouter plus de cas à partir de l'œuf"), avec plus spécifiques à l'interface des matchs de prendre la priorité sur les moins-des rencontres spécifiques (Interface classes peuvent être des sous-classes de l'un à l'autre, et c'est exactement ce que vous espérer qu'il ferait.)

    Cartes à partir d'un Interface peut être appelée avec une très belle syntaxe, ISomething(object_to_adapt), ou peut être regardé par l'intermédiaire de la fonction zope.component.getAdapter. Les adaptateurs de plusieurs Interfaces ont à être regardé par l'intermédiaire de la fonction zope.component.getMultiAdapter, ce qui est un peu moins jolie.

    Vous pouvez avoir plus d'une carte pour un ensemble donné de Interfaces, différenciés par une chaîne de caractères name que vous fournissez lors de l'inscription de la carte. Le nom par défaut est "". Par exemple, BrowserViews sont en fait des cartes qui s'adaptent à partir de l'interface qu'ils sont enregistrés sur et une interface de l'HTTPRequest classe implémente. Vous pouvez aussi voir tous les adaptateurs qui sont enregistrés à partir d'une séquence de Interfaces à l'autre Interface, à l'aide de zope.component.getAdapters( (IAdaptFrom,), IAdaptTo ), ce qui renvoie une séquence de (nom de l'adaptateur) paires. Il peut être utilisé comme une très belle façon de fournir des crochets pour les plugins de s'attacher à des.

    Dire que je voulais sauver tous mes articles du blog et de la configuration comme un gros fichier XML. J'ai créer un my.blog.xmldump d'œufs qui définit un IXMLSegment, et les registres d'une carte d' IBlogPost de IXMLSegment et d'une carte d' IBlogConfiguration de IXMLSegment. Je peux maintenant appeler selon adaptateur est approprié pour un objet que je veux pour sérialiser en écrivant IXMLSegment(object_to_serialize).

    Je pourrais même ajouter plus de cartes à partir de divers autres choses à IXMLSegment d'œufs autres que my.blog.xmldump. ZCML a une fonction où il peut exécuter une directive particulière si et seulement si l'oeuf est installé. Je pourrais utiliser pour avoir my.blog.rss enregistrer une carte à partir d' IRSSFeed de IXMLSegment mfi my.blog.xmldump arrive à être installé, sans faire de my.blog.rss dépendent my.blog.xmldump.

  4. Viewlets sont comme des petits BrowserViews que vous pouvez avoir "s'abonner" à un endroit précis à l'intérieur d'une page. Je peux pas me souvenir de tous les détails maintenant, mais ce sont de très bons pour des choses comme les plugins que vous souhaitez voir apparaître dans la barre latérale.

    Je ne me souviens pas si désinvolte qu'ils font partie de la base de Zope ou Plone. Je déconseille l'utilisation de Plone, à moins que le problème que vous essayez de résoudre réellement besoin d'une véritable CMS, car c'est un grand et compliqué morceau de logiciel et il a tendance à être un peu lent.

    Vous n'avez pas nécessairement besoin réellement Viewlets de toute façon, depuis BrowserViews pouvez appeler l'un de l'autre, soit à l'aide de l'objet/@@some_browser_view " dans un TAL expression, ou par l'utilisation d' queryMultiAdapter( (ISomething, IHttpRequest), name='some_browser_view' ), mais ils sont assez sympa malgré tout.

  5. Marqueur Interfaces. Un marqueur Interface est Interface qui ne fournit aucune méthode et sans attributs. Vous pouvez ajouter un marqueur Interface tout objet lors de l'exécution à l'aide de ISomething.alsoProvidedBy. Ceci vous permet, par exemple, modifier des adaptateurs sera utilisée sur un objet particulier et qui, BrowserViews sera défini sur elle.

Je m'excuse que je n'ai pas disparu dans suffisamment de détails pour être en mesure de mettre en œuvre chacun de ces exemples, tout de suite, mais qu'ils avaient de prendre environ un blog chaque.

23voto

Ruslan Spivak Points 692

Vous pouvez réellement tester si votre objet ou votre classe implémente votre interface. Pour cela, vous pouvez utiliser le module verify (vous l'utiliseriez normalement dans vos tests):

 >>> from zope.interface import Interface, Attribute, implements
>>> class IFoo(Interface):
...     x = Attribute("The X attribute")
...     y = Attribute("The Y attribute")

>>> class Foo(object):
...     implements(IFoo)
...     x = 1
...     def __init__(self):
...         self.y = 2

>>> from zope.interface.verify import verifyObject
>>> verifyObject(IFoo, Foo())
True

>>> from zope.interface.verify import verifyClass
>>> verifyClass(IFoo, Foo)
True
 

Les interfaces peuvent également être utilisées pour définir et tester des invariants. Vous pouvez trouver plus d'informations ici:

http://www.muthukadan.net/docs/zca.html#interfaces

19voto

David Glick Points 4094

Zope interfaces peuvent fournir un moyen utile de dissocier les deux morceaux de code qui ne devrait pas dépendre les uns des autres.

Disons que nous avons un composant qui sait comment faire pour imprimer un message d'accueil d'un module.py:

>>> class Greeter(object):
...     def greet(self):
...         print 'Hello'

Et un peu de code qui a besoin d'imprimer un message d'accueil dans le module b.py:

>>> Greeter().greet()
'Hello'

Ainsi, il est difficile de remplacer le code qui gère le salut sans le toucher.b.py (qui pourrait être distribué dans un paquet séparé). Au lieu de cela, nous avons pu introduire un troisième module c.py qui définit un IGreeter interface:

>>> from zope.interface import Interface
>>> class IGreeter(Interface):
...     def greet():
...         """ Gives a greeting. """

Maintenant, nous pouvons l'utiliser pour découpler un.py et b.py. Au lieu d'instancier une classe Greeter, b.py va maintenant demander un utilitaire de fournir le IGreeter interface. Et un.py déclare que la classe Greeter implémente cette interface:

(a.py)
>>> from zope.interface import implements
>>> from zope.component import provideUtility
>>> from c import IGreeter

>>> class Greeter(object):
...     implements(IGreeter)
...     def greet(self):
...         print 'Hello'
>>> provideUtility(Greeter(), IGreeter)

(b.py)
>>> from zope.component import getUtility
>>> from c import IGreeter

>>> greeter = getUtility(IGreeter)
>>> greeter.greet()
'Hello'

2voto

Daniel Naab Points 9857

Je n'ai jamais utilisé d'interfaces Zope, mais vous pouvez envisager d'écrire une métaclasse qui, lors de l'initialisation, vérifie les membres de la classe par rapport à l'interface et lève une exception d'exécution si une méthode n'est pas implémentée.

Avec Python, vous n'avez pas d'autres options. Soit une étape de "compilation" qui inspecte votre code, soit une inspection dynamique au moment de l'exécution.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X