a pinch of indirection, and dont cut yourself chopping onions
TRANSCRIPT
![Page 1: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/1.jpg)
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)
![Page 2: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/2.jpg)
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
![Page 3: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/3.jpg)
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
![Page 4: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/4.jpg)
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
![Page 5: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/5.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
![Page 6: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/6.jpg)
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
![Page 7: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/7.jpg)
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)
![Page 8: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/8.jpg)
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
![Page 9: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/9.jpg)
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)
![Page 10: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/10.jpg)
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)
![Page 11: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/11.jpg)
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
🌶
![Page 12: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/12.jpg)
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
![Page 13: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/13.jpg)
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
![Page 14: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/14.jpg)
Principles and patterns
#ploneconf2016|@sdupton
![Page 15: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/15.jpg)
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
![Page 16: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/16.jpg)
“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
![Page 17: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/17.jpg)
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
![Page 18: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/18.jpg)
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
![Page 19: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/19.jpg)
Now, I’m just being contrary…
#ploneconf2016|@sdupton
![Page 20: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/20.jpg)
Simplified API Love/hate
THIS: NOTTHIS:
#ploneconf2016|@sdupton
![Page 21: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/21.jpg)
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
![Page 22: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/22.jpg)
…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
![Page 23: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/23.jpg)
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
![Page 24: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/24.jpg)
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
![Page 25: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/25.jpg)
“Just enough”Zope Component Architecture
…andwhattodowhenitwon’tcooperate.
#ploneconf2016|@sdupton
![Page 26: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/26.jpg)
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
![Page 27: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/27.jpg)
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
![Page 28: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/28.jpg)
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
![Page 29: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/29.jpg)
Methods in interfaces
#ploneconf2016|@sdupton
Debatable merit?
![Page 30: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/30.jpg)
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
![Page 31: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/31.jpg)
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
![Page 32: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/32.jpg)
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
![Page 33: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/33.jpg)
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
![Page 34: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/34.jpg)
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
![Page 35: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/35.jpg)
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
![Page 36: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/36.jpg)
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
![Page 37: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/37.jpg)
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
![Page 38: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/38.jpg)
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
![Page 39: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/39.jpg)
Related technologies
#ploneconf2016|@sdupton
![Page 40: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/40.jpg)
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
![Page 41: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/41.jpg)
Outside the (server) box
TransplantingcomponentideologyintoaJavaScriptenvironment.
#ploneconf2016|@sdupton
![Page 42: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/42.jpg)
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
![Page 43: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/43.jpg)
“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
![Page 44: A pinch of indirection, and dont cut yourself chopping onions](https://reader031.vdocuments.net/reader031/viewer/2022030402/58752a521a28ab3f098b647d/html5/thumbnails/44.jpg)
#ploneconf2016|@sdupton
In food and in software, there is always room for good cooking.