Upload
sean-upton
View
241
Download
0
Embed Size (px)
Citation preview
A Pinch of IndirectionAnd don’t cut yourself chopping onions…
... practical tips for using component architecture(s).
SeanUptonUniversityofUtahDepartmentofPediatrics/UPIQ.org
#ploneconf2016|@sdupton
Photocredit:https://www.flickr.com/photos/ampersandyslexia (CC:by-sa)
Hello Boston!
This talk is about (pick one):
(a) Plone(b) Food(c) Components(d) APIs(e) Some, none, or all of the above.
#ploneconf2016|@sdupton
All uncredited photos in this slide deck:© 2013-2016 Sean Upton, free for your re-use via CC-by-3.0
The topic…
• Let’s talk about components• Idioms and helpful ideas• Cooking analogies• Round and round we go: how many #ploneconf ZCA
talks have there been over the years? Why this, why now?
• I have opinions.– There might even be JavaScript involved.– Run while you still can!
#ploneconf2016|@sdupton
Photocredit:https://en.wikipedia.org/wiki/Penrose_stairs
This Old Hat
Theoldhatsurelybeats… …thenewhat?
#ploneconf2016|@sdupton
Photocredit:©HBO(usedhereunderfairuse)Photocredit:GarySteward(CC-by-3.0)
https://commons.wikimedia.org/wiki/File:Bullwhip_and_IJ_hat.jpg
Components are our craft!
• Our “old hat” dates 1.5 decades. It is weathered, sturdy -- not rotting in the fridge.
• Anyway, we are in Boston, home to public television show “This Old House”…– And some of the best American food media have
roots here too.– Plan for kitchen metaphors "peppered" throughout
the discussion... • Components are relevant part of our craft.
#ploneconf2016|@sdupton
Goals
• Talk about components; – ...in the kitchen of Python; – ...in the fine dining experience of Plone; – ...in "foreign cuisine" (e.g. JavaScript).
• Explore idioms and ideas• Motives: why does this approach matter?• Hacks, workarounds, surviving a bit of
pdb.set_trace()
#ploneconf2016|@sdupton
No fear!
• Complexity is okay, if essential.• Components solve problems.• I am probably more contrarian than necessary about
simplified "public" APIs (though I use them).
#ploneconf2016|@sdupton
"If you're convinced that cooking is drudgery, you're never going to be good at it, and you might as well warm
up something frozen." -- James Beard
Photo:JamesBeardFoundation (usedhereunderfairuse)
Disclaimers
• I am not sure if this talk is about software architecture, development practice, or cooking.
• All truths are contingent on your own practical realities.
• I hope to impart three things:– Why and how I think ZCA matters to all kinds of
developers on this platform.– A few scattered ideas on making use easier.– Applications outside the box (e.g. JavaScript).
#ploneconf2016|@sdupton
A brief history…
• "Zope 3" – Motivations spurred from
anxiety over mixin mazes • Trying to solve the Z-shaped
learning curve?• We still have these mazes today
(e.g. read Zope 2 OFS.* source).– Community absorbed the complexity
that works, ignored what didn’t?
#ploneconf2016|@sdupton
• IIRC, my earliest recollection is 2002 BOF at OSCON with Jim Fulton
Photocredit:https://commons.wikimedia.org/wiki/File:Inside_a_corn_maze_near_Christchurch,_New_Zealand.JPG(publicdomain)
Now ZCA + ZTK
• Frombiggerstacktosmallerparts– Mirepoix,notthewholesouppot.
– Buffet,nottabled'hôte/prixfixe
– Eatwhatyouwant.• e.g.Twistedusesonly
zope.interface
#ploneconf2016|@sdupton
Photo credits: via WikiMedia Commonshttps://commons.wikimedia.org/wiki/File:Onion_on_White.JPG (CC-by-sa)
https://commons.wikimedia.org/wiki/File:C%C3%A9leri.jpg (CC-by-sa)https://commons.wikimedia.org/wiki/File:Baby_Carrots_2.jpg (CC-by-2.0)
https://upload.wikimedia.org/wikipedia/commons/4/44/Mirepoix_on_cutting_board.jpg(CC:by-sa)
The “holy trinity” of componentsAdapters
üSingle contextüViews and multiple contextüSubscribers (event notification)
ResourcesüContentüUtilitiesüRequest/response
Schema…because resources are nouns, why think in verbs?
#ploneconf2016|@sdupton
🌶
Categorizing objects
• There are two broad categories of objects – Those you look up
• By path (content traversal)• By component registry• By both (views)
– Those you don't• But many of these are in the service of some kind of lookup:
– Request objects (object publishing)• Site-global state
– But plone.app.registry makes even this less likely.
• We have indirection everywhere; that’s okay.
#ploneconf2016|@sdupton
Indirection
• Scary departure from imperative programming?
• You still will eventually end up in the debugger.• We get a lot of flexibility, and very consistent
idioms doing this.• Components are the mirepoix of good
software, registries are our larder.• Using adapters does not require a registry, but
it does help keep the kitchen tidy.
#ploneconf2016|@sdupton
Principles and patterns
#ploneconf2016|@sdupton
Recipe-driven development
1. Write interfaces first;
2. then tests, often doctests;
3. write your implementation(s);
4. refine and adjust.
5. Break the build (hey, it happens sometimes!)
#ploneconf2016|@sdupton
“Design by contract”
• Who on Earth thinks this is a trademark-worthy phrase?
• Interfaces are contracts.• We can use multiple implementations to fulfill
contracts.• This is a good thing– Form widgets– Separation of concerns– Test to the interface, not to the implementation.
#ploneconf2016|@sdupton
Component Corollary #1: Language Idioms
• Make components that look like native Python data structures!– Mappings– Sequences– Sets
• If you do this, chances are you will represent things as nouns, not verbs.
• Resource-centric development
#ploneconf2016|@sdupton
Resource-centric Development
• Driven by state, not by action• Placeful, often.• M in MVC matters more than V, C.• Our community and our platform has unique
talents:– Traversal, Traversal, Traversal!– Persistent objects: objects are first class, they are the
things we want, not mere proxies.• Components should be more noun than verb,
suiting both platform and language idioms.#ploneconf2016|@sdupton
Now, I’m just being contrary…
#ploneconf2016|@sdupton
Simplified API Love/hate
THIS: NOTTHIS:
#ploneconf2016|@sdupton
APIs
Procedural• Benefit:simplifytosingle
resource:thesite.– Butnow,thesiteismega-
controller.• Costs:
– Doesnotalwaysrepresentwhatweareworkingwith.
– Leakyabstractions(e.g.IPropertiedUser).
– Lostopportunityatsimplifiedresource/noun/stateidioms.
State-driven• Benefits:
– Componentsobeyidioms– Componentslooklikestatethey
directlyrepresent.• Cost:youmusttraversetothe
resourceyouwanttoworkwith.– Isthatsuchabadthing?– Sometimesthisistraversaltoa
folder,insteadofusingthesiteasacontroller.MoreOO.
– Sometimescomponentlookup.
#ploneconf2016|@sdupton
…at it’s most hyperbolic:
• Are procedural APIs the "frozen microwave meal" of software design?– They have utility;– Some can be quite good;– Not always as satisfying or complete as the heart
of component-driven software.• Placeful interfaces (e.g. traversal) made clean
URLs before the cool kids in the other frameworks thought about routes, mappings, and slugs.
#ploneconf2016|@sdupton
These approaches are not mutually exclusive.
• I can and do use parts of plone.api I like or that save me time.
• I can use components that have state, place --and don’t act procedurally.
• I can mix these.• I’m okay with that.• Use procedural APIs when they save time or
help learning curve – however, imperative, action-driven code is not always appropriate.
#ploneconf2016|@sdupton
My point
• Components, ZCA are not just for ninjas.• Keep your kitchen appliances, but know how to
handle a knife without cutting yourself! • You should not be afraid to get a knick or two. Even
pro chefs have scars. Scars teach.• Sometimes it’s okay to buy pre-cut Mirepoix from
Whole Foods. I won’t tell, or judge.• I even bought a frozen Chicken Tikka meal from Trader
Joes last week.• I do make my own stock, but don’t grind my own
sausage. Make choices you are comfortable with.
#ploneconf2016|@sdupton
“Just enough”Zope Component Architecture
…andwhattodowhenitwon’tcooperate.
#ploneconf2016|@sdupton
zope.interfaceComponents are “objects connected by interfaces”
• Fundamental to all of this.• Should infuse how you think and write code.• Interface is a contract for behavior and state.
#ploneconf2016|@sdupton
“What's important about components is that you can put them together. Interfaces are the mechanism for connecting things. “
-- Jim Fulton in 2004 [1]
[1]:http://ftp.ntua.gr/mirror/python/pycon/dc2004/papers/3/PyCon2004ZopeRoadmap.pdf
Separation of concerns
• Content type implementations should not do much. Separate concerns, and…
• ...write adapters that do heavy lifting (actions) and transformation.
• Resources work much better with pluggable components, whether widgets, behaviors, etc.
• Make global functionality site-independent.• OO by composition, not inheritance.
#ploneconf2016|@sdupton
Schema
• Let’s suppose we have a recipe system.
• Where each ingredient is stored with structured data, in a grid.
• The recipe is just about state, as is its ingredients.– Describe state (schema)– Store state (content)
#ploneconf2016|@sdupton
Methods in interfaces
#ploneconf2016|@sdupton
Debatable merit?
Adapters
• Fetch density (utility, or adapter of site)• Give me metric• Give me fractions! Or decimals!• Give me volume to weight! Or vice-versa.• Each with specific concern, purposeful, pluggable.
#ploneconf2016|@sdupton
Adapters usually registered
• Adapter declares it implements an interface.• Python or ZCML declares what adapter
adapts.• ZCML registers adapter in (usually global)
component registry.• Lookup is by calling interface:
adapter = IIngredientFormatter(my_ingredient)title = adapter()
#ploneconf2016|@sdupton
When registrations attack• Pdb needs a bit of help from you before you dive into
debugging adapter, widget, and event subscriber registration problems.– Move _zope_interface_coptimizations.so out of your
zope.interface distribution;– Restart, coffee, debug;– Fix it, coffee, really fix it;– Move the optimizations back into place.
• Specificity helps, sometimes you need to resort to interface subclassing to make your registrations more specific.
#ploneconf2016|@sdupton
Browser Views
• Other frameworks see views as endpoints to URLs.
• We see views as all about context.• Multi-adapter: a view is a component that
takes a resource (e.g. content) and a request, and makes a response.– Placeful– Graceful– All about the content!
#ploneconf2016|@sdupton
Global utilities
• Useful for site-agnostic things like:– Vocabulary lookups– Integration with other services (e.g. message or job
queues)– Quick static transformation of content that needs no
configuration.– Object serialization or cryptographic signing– Custom field types for plone.schemaeditor
#ploneconf2016|@sdupton
Vocabularies
• When we write schema for ”Choice” type fields, we need choices.
• Sometimes this is static (in your Python or your supermodel XML for a TTW type).
• Sometimes, you want a dynamic source.– Stock global: e.g. timezone– Site or context-local: e.g. show only items in navroot.
• Used for enumeration and/or validation.– Sometimes, just one or the other.
#ploneconf2016|@sdupton
Site-global functionality
• Four approaches– Persistent component (utility)– Adapter-of-site– plone.api functions, where applicable.– CMF tools (deprecated)
• If you need to store state in the site, you likely need to choose between the first two.
#ploneconf2016|@sdupton
Persistent utilities
• Can store state in ZODB: good.• Uninstalling can be a hard problem: bad.• Cache data in _v_ attrs across requests: good.• No need for proxies – data, methods in one
place: good.• Requires use of
zope.component.hooks.setSite.• Might be responsible for the 2008 global
recession? ;-)
#ploneconf2016|@sdupton
Adapter of site
• Needs to be cheap to construct, because you will do this more than once, though you can avoid doing more than once per request if clever.
• No need for setSite() in scripts.• No uninstallation nightmares.• Forces you to think about how to use OOTB
data structures in Annotations: good or bad, depending on need.
#ploneconf2016|@sdupton
Related technologies
#ploneconf2016|@sdupton
Related, worth mention• Martijn Faassen’s Reg (and Morepath)• Python ABCs– Pauper’s interface– IMHO, problem:
• “Is a” is possible relationship• “As a” is not• No per-instance markers, no per-instance behavior based on
such.– E.g. https://github.com/seanupton/experimental.flavors
» Disclaimer: may suffer some bit rot.
– Better critique: • https://glyph.twistedmatrix.com/2009/02/explaining-why-interfaces-are-great.html
#ploneconf2016|@sdupton
Outside the (server) box
TransplantingcomponentideologyintoaJavaScriptenvironment.
#ploneconf2016|@sdupton
Some examples
• For UPIQ, I recently wrote:– A mockup widget that extends PickADate, using an
adapter pattern (but not any kind of component presumptions otherwise).
– Several incarnations of JavaScript zope.schemalook-alikes. I will briefly show you what one of these looks like; I see much promise in the idea.
– https://github.com/upiq/plotqi/blob/master/spec/modelref/dataviz.js#L357
• We plan to write a 100% JavaScript forms library based on client-side schema, that groks plone.supermodel XML.
#ploneconf2016|@sdupton
“Components” vs “Web Components”• My use of “component architecture” in
JavaScript is distinct from “web components”:– We can have schema in JavaScript.
• And resource-centric development, validation, etc.• And design by contract for applications where JSON is an
interchange format. JSON Schema is very limited.– We could have component registries in JavaScript, if
we wanted.– We can use adapters, we could try using
synchronous event notification as adjunct to asynchronous callback ideology.
– Form applications are an opportunity.
#ploneconf2016|@sdupton
#ploneconf2016|@sdupton
In food and in software, there is always room for good cooking.