Loading…

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

Like this presentation? Why not share!

Design and development with dexterity and convention over configuration

on

  • 2,440 views

Martin Aspeli's talk from the Plone Conference 2010 in Bristol, UK

Martin Aspeli's talk from the Plone Conference 2010 in Bristol, UK

Statistics

Views

Total Views
2,440
Views on SlideShare
2,440
Embed Views
0

Actions

Likes
1
Downloads
55
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />

Design and development with dexterity and convention over configuration Design and development with dexterity and convention over configuration Presentation Transcript

  • Design and Development with Dexterity and Convention over Configuration Martin Aspeli Plone Conference 2010
  • Dexterity and convention over configuration Overview What we will cover today Design principles A few rules of thumb What is a content type? Not everything is best modelled as content What is a view? Just like any other web framework What is a component? Not quite like every other web framework Putting it all together Decisions and lessons More information What to read next
  • Dexterity and convention over configuration About this session Plone gives us a powerful, if somewhat bewildering toolbox. If all you have know is a hammer Archetypes, everything looks like a nail base_edit. This talk is based on a real world project • A website with a large amount of content • Bespoke e-commerce (gambling) • Content management within the gaming areas • Lots of web services • High volume, uneven load patterns We will talk mainly about design today, but point to more in-depth tutorials that will teach you the syntax.
  • Design and Development with Dexterity and Convention over Configuration Martin Aspeli Plone Conference 2010
  • Design principles A few rules of thumb Dexterity and convention over configuration
  • Dexterity and convention over configuration Dubious metaphor #1: Code is like a plastic bag Reduce Re-use Recycle Write as little code as Use the built-in content types Plone gives us UI and possible wherever possible tools like workflow. Use these when they Use existing add-ons (and help. ‣ Dexterity = Archetypes ÷ verbosity contribute) if you can ‣ five.grok = When they don’t, start components ÷ ZCML ‣ archetypes.schemaextender writing ‘normal’ web is the gateway drug application code. ‣ z3c.form = schema ÷ content type ‣ Search PyPI before building something new ‣ We’ll call this “breaking out”
  • Dexterity and convention over configuration Not everything is best modelled as content What is a content type?
  • Dexterity and convention over configuration In Dexterity (and CMF) game.py: Define the fields in your type. class IGame(Interface): Drives default forms, Schema title = schema.TextLine( validation, security and title=”Name of game”, programmatic interaction. ) + Tell Plone about your content profiles/default/types/game.xml: type and how it is to be FTI constructed. <object> ... </object> Define how the type looks. + game.py: There can be many views, but usually one default one. class View(grok.View): grok.context(IView) grok.require(‘zope2.View’) Forms are a special type of View(s) view. We usually stick with the def update(self): auto-generated forms, but it is # any logic here easy to override these. game_templates/view.pt: <html> ... </html>
  • Dexterity and convention over configuration When to build a custom content type When... But not when... • Plone’s content management UI is a • You just need a form. natural fit ‣ Use z3c.form (view) or ‣ Adding PloneFormGen (content) ‣ Editing • Your data is relational ‣ Viewing ‣ Common symptom: you need a ‣ Navigating lot of references ‣ Searching ‣ Use a custom form (z3c.form) and relational database (via • You want to use Plone’s workflow engine z3c.saconfig/SQLAlchemy) • Your information is hierarchical • You are fighting the framework ‣ If it feels wrong, it probably is
  • Dexterity and convention over configuration Modelling with content types Schema fields: Use for basic data, references (but not to “Folder” children). Type Title Sometimes use for file/ Description image data, but child Other fields object is often better. “Item” Use for “content managed” text and Child type Title settings that affect how Description views are rendered or Other fields process forms. Consider storing images, “One to many” sub-pages and other relationship. resources also. Use plone.registry for Defined in the global information. FTI.
  • Dexterity and convention over configuration Example gamesystem.py profiles/default/types/gamesystem.xml class IGameSystem(form.Schema): <?xml version="1.0"?> <object name="gamesystem" meta_type="Dexterity FTI"> title = schema.TextLine( <property name="title">Game System</property> title = u"Name", ... ) <property name="allowed_content_types"> <element value="game" /> description = schema.Text( <element value="Document" /> title = u"Description", <element value="Folder" /> required=False, </property> ) <property name="schema">acme.gaming.gamesystem.IGameSystem</ body = RichText( property> title = u"Body", <property required=False, name="klass">plone.dexterity.content.Container</ ) property> <property name="add_permission">acme.AddGame</ property> <property name="behaviors"> <element value="plone.app.content.interfaces.INameFromTitle" /> </property> ... </object>
  • Dexterity and convention over configuration Just like every other web framework? What is a view?
  • Dexterity and convention over configuration Views in Zope and five.grok A URL resolves to a Implements basic rendering published resource, in this case a view. grok.View Published resource Triggers configuration Looked up as a MyView Named multi- adapter update() Automatic Implemented by association <module>_templates/ Class Template myview.pt Calls
  • Dexterity and convention over configuration When to create a new view When... But not when... • You are defining how a content type is • You want something in the to be rendered navigation tree • You are defining an alternative view ‣ Only content shows up in the site of a content type navigation ‣ Perhaps not using Plone’s UI • You want to store data that fits the • You are creating a standalone form or content model dynamic view ‣ Usually easier to create a ‣ Register a view on the site root content type • You are coding a form action ‣ Sometimes we create views to capture information for an ‣ No need for a template, e.g. external system (e.g. database) result in a redirect • You are defining a dynamic resource ‣ e.g. XML representation of a content object
  • Dexterity and convention over configuration Example playhistory.py playhistory_templates/getplayhistory.pt class GetPlayHistory(grok.View): <html> grok.context(IGamingSstem) <body> grok.require('acme.ManageAccount') grok.name('view-play-history') <metal:main fill-slot="main"> <tal:main-macro def update(self): metal:define-macro="main"> channel = getUtility(IServiceChannel) session = ISession(self.request) .... form = self.request.form </metal:main> self.history = self.getHistory(channel, session, form) </body> </html> def getHistory(self, channel, session, form): response = None userId = session[PlayerSessionKeys.userId] tokenId = session[PlayerSessionKeys.tokenId] return channel.service.searchGamingHistory( tokenId, gameId, status, dateFrom, dateTo, pageId, )
  • Dexterity and convention over configuration Not quite like every other web framework What is a component?
  • Dexterity and convention over configuration Adapters, utilities, event subscribers Adapter Utility Subscriber Basically: Change one Global, stateless services. React to events, usually interface to another for a specific content type. Also: Registry of homogenous In practice: Extension named components Plone fires content events. point ‣ Useful for building your own ‣ Hook into the content ‣ Override adapters to services management process change Plone’s ‣ Look up and use Plone’s ‣ Decouple your own code behaviour services ‣ Create your own ‣ Sometimes use to override extension points global behaviour
  • Dexterity and convention over configuration When to reach for components When... But not when... • You are implementing re-usable • You don’t need to business logic • It complicates your design ‣ Use a utility ‣ You can always refactor later ‣ Call from a view or subscriber • You need to hook into the content management process (add, edit, delete, etc) ‣ Register an event subscriber • You need to create or use an extension/customisation point ‣ Use an adapter
  • Dexterity and convention over configuration Examples* class SOAPServiceChannel(grok.GlobalUtility): grok.provides(IServiceChannel) @property def service(self): return self._getClient().service ... @grok.subscribe(IGameSystem, IObjectAddedEvent) def addDefaultContent(context, event): context.invokeFactory(‘Document’, ...) .... * I would not find a useful example of an adapter anywhere in our code. There was one obtuse multi-adapter, but I don’t want to hurt your brain
  • Dexterity and convention over configuration Decisions and lessons Putting it all together
  • Dexterity and convention over configuration What we did Content space For global settings: Avoid hard- coding things Registry ‘Traditional web application’: View processes form, “Break out” - Login renders stores settings for information, gaming system, redirects. security controls Gaming MyAccount access to gaming, System views are the UI 1 to the web MyWallet application. - gs for s for View logic makes m, m, Game-specific * database Play rols rols data. Contains a connections ming, ming, key that connects Game (SQLAlchemy) and e UI UI to underlying web service calls database and web View results (Suds) service.
  • More information What to read next Dexterity and convention over configuration
  • Dexterity and convention over configuration Recommended reading The Dexterity developer manual A comprehensive guide to Dexterity http://plone.org/products/dexterity/documentation/manual/developer-manual The five.grok manual Zope components and views using convention-over-configuration http://plone.org/products/dexterity/documentation/manual/five.grok The plone.directives.form manual Basics of z3c.form using convention-over-configuration http://plone.org/products/dexterity/documentation/manual/schema-driven-forms The archetypes.schemaextender documentation http://pypi.python.org/pypi/archetypes.schemaextender