<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>Let’s Discuss the Matter Further</title>
    <link>http://rhodesmill.org/brandon</link>
    <description>Your Blog's short description</description>
    <pubDate>Thu, 19 Jan 2012 00:48:19 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Python at the 2009 Atlanta Linux Fest</title>
      <link>http://rhodesmill.org/brandon/2009/python-at-atlanta-linux-fest/</link>
      <pubDate>Mon, 21 Sep 2009 23:17:06 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[plone]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/?p=238</guid>
      <description>Python at the 2009 Atlanta Linux Fest</description>
      <content:encoded><![CDATA[
<div class="caption" style="width: 100%;">
  <img src="http://rhodesmill.org/brandon/static/2009/alf2009-python-booth.jpg"
       alt="GetPaid for Plone logo"
       width="420" height="315" />
  <p style="padding-left: 3em; padding-right: 3em; text-align: center;">
  My Python table at the Atlanta Linux Fest.
  You can
  <a href="http://rhodesmill.org/brandon/static/2009/alf2009-python-booth.mpg"
     >also watch a short video of me demonstrating a depth-first search</a>
  to some students who dropped by the table.
  (Thanks, Richard Davies, for the video!)
</div>
<p>
  Running the Python table at the
  <a href="http://atlantalinuxfest.org/">Atlanta Linux Fest</a>
  this past weekend was a really incredible experience.
</p>
<p>
  First, there was the great feeling
  that the pillars of the Python community were standing behind me
  as I stepped forward to represent my favorite programming language.
  It was <a href="http://www.amk.ca/">Andrew Kuchling</a>
  who noticed that exhibitor tables at the Fest were free
  for non-profits like the
  <a href="http://www.python.org/psf/">Python Software Foundation</a>,
  and <a href="http://holdenweb.com/">Steve Holden</a>
  who forwarded me a heads-up since I live in Atlanta
  (the Fest had not yet made it on to my radar).
  The inimitable <a href="http://rule6.info/">Aahz</a>
  personally shipped me the promotional kit,
  including a huge “Python” banner and stacks of brochures,
  that he himself had just used
  at <a href="http://en.oreilly.com/oscon2009">OSCON 2009</a>.
  And, completing the loop, it was Andrew who followed up
  to ask if there were any last things that I needed,
  and sent me a pile of over one hundred Python stickers
  that wound up being <i>very</i> popular at the Fest.
  (I returned home with exactly one,
  which is sitting next to me on my desk as I type this!)
</p>
<p>
  Here are some lessons that I learned from the experience:
</p>
<!--more-->
<ul>
  <li>
    <p><b>Reserve a table.</b></p>
    <p>When I got the email saying
      that the PSF could have an exhibitor table for free,
      and asking whether anyone was available to run it,
      I somehow assumed that my affirmative reply
      would spur some busy PSF staffer
      into sending an email, on official nonprofit letterhead,
      reserving a table for us at the event.
    </p>
    <p>
      You can imagine my dawning panic
      as I arrived at the Fest —
      amidst these torrential Atlanta downpours,
      and with my arms full of Python advocacy paraphernalia —
      and started looking for the table reserved for Python.
      It was, I think, after my second full tour of the room
      that it started to dawn on me that it must have been <i>my</i>
      responsibility to reserve the table on the PSF's behalf.
    </p>
    <p>
      I stashed the Python materials safely next to a flower pot
      that provided adequate camouflage,
      and returned to the front desk.
      And, here, that wonderful camaraderie kicked in
      that, at its best, blossoms between even the most distant
      contingents of the Open Source world.
      When I explained the problem to a Linux Fest volunteer,
      and he found the organizer obviously too busy to address the problem,
      he made a unilateral decision to grant me a booth himself
      and we set out immediately in search of an extra table.
      A few minutes later,
      I was ensconced in a prize position in the exhibit hall,
      and was figuring out how to hang the Python banner.
    </p>
  </li>
  <li>
    <p><b>Enjoy the glory that is the Python banner.</b></p>
    <p>
      Seriously. Take a look at the picture that opens this blog entry.
      The banner was larger than every other banner in the room.
      Well, okay,
      there was one group,
      the <a href="http://www.opennms.org/wiki/Main_Page">OpenNMS</a>
      folks,
      who might actually have had a banner that matched ours in size,
      but the word “Python” was certainly the biggest single
      word in the entire room.
      It attracted attention,
      and started many of the conversations
      that made running the table such fun.
    </p>
  </li>
  <li>
    <p><b>Bring string.</b></p>
    <p>
      I was actually pulling out into my driveway,
      and consulting my mental what-to-bring list,
      when I realized that my spool of string
      was still sitting in my garage.
      Thank goodness I stopped the car and ran back inside;
      without that string,
      and Josh Kidd's ability to push thumb tacks into concrete walls,
      the Python banner would have had to hang limply
      beneath our table instead.
    </p>
  </li>
  <li>
    <p><b>You will find yourself, first and foremost,
        encouraging and rallying other Python programmers.</b></p>
    <p>
      This surprised me.
      I had somehow imagined that most of my conversations
      would be with strangers to Python,
      whose skepticism would need to be slowly chipped away
      as I ranted on about the wonders of my favorite language.
      But many people had already run into Python,
      liked what they saw,
      and now wanted to learn more about the language.
      The locals were happy to be invited to our Atlanta Python Meetup,
      and others listened carefully
      as I described how I myself had slowly learned how to follow
      what was happening in the Python community.
    </p>
    <p>
      And several people didn't even have anything to say.
      They just paused on their way by,
      saw the pile of stickers,
      and smiled appreciatively as they grabbed several
      on their way to the next booth.
    </p>
  </li>
  <li>
    <p><b>Have people with different Python experiences
        manning your booth.</b></p>
    <p>
      It was great to have several other Python Atlanta folks
      help with the table through the day.
      In particular,
      Josh Kidd spent several hours with me,
      and fielded the many questions
      that came up when people saw
      the <a href="http://plone.org/">Plone</a> labels and bumper stickers
      that Josh had brought from the ifPeople offices.
    </p>
  </li>
  <li>
    <p><b>Greet people.</b></p>
    <p>
      Walking up to an exhibitor table, I find,
      can be an awkward experience.
      Sometimes the exhibitor fails to acknowledge me,
      which makes me feel like I am interrupting.
      Or they stare expectantly,
      and make it <i>my</i> job to start the conversation.
    </p>
    <p>
      My foundational goal with everyone who approached the table
      was to create a space in which they felt welcomed,
      but not required to say anything if they didn't want to.
      Soon, with a bit of practice,
      words like these were coming easily to my lips:
      “Hi, I'm Brandon Rhodes;
      I organize the Python Atlanta user's group,
      and make my living programming in Python.
      Let me know if you have any questions!”
    </p>
  </li>
  <li>
    <p><b>Bring a monitor.</b></p>
    <p>
      As you can see in the image above,
      I connected the monitor to my laptop
      and pointed it at the audience,
      expecting that I would regale them
      with a steady stream of impromptu Python scripts
      and rapid prototypes
      built using the many powerful libraries
      and frameworks available in Python.
    </p>
    <p>
      But, its greatest value turned out to be as a web browser:
      instead of telling someone where to find the Python tutorial,
      or vaguely gesturing as I tried to describe matplotlib,
      I could drag a Firefox window on to the monitor
      and just show them the web site.
      Better yet,
      they now knew what the sites looked like
      and would hopefully recognize them again
      if they went and looked after the conference.
    </p>
    <p>
      That's not to say that there weren't a few times
      that I got to give Python demonstrations.
      As shown
      <a href="http://rhodesmill.org/brandon/static/2009/alf2009-python-booth.mpg"
         >in the video clip linked to at the top of this page</a>,
      I got to demonstrate several basic algorithms —
      including depth-first and breadth-first tree searches —
      for some friendly Georgia Tech students.
      Another group who approached
      (they looked older, like grad students or post-docs)
      included someone who had used Python,
      but who had found it tricky to write a loop
      that would correctly delete items from a list
      while iterating across it.
      They stayed glued to the screen
      for what must have been fifteen minutes
      while I used the question as a jumping-off point
      for demonstrating Python list indexing,
      how deleting an element during iteration
      causes you to skip the next one,
      how iteration is usually not even necessary
      thanks to built-in list methods like <tt>remove()</tt>,
      and, finally, about list comprehensions and filters.
      It was actually the wide array of built-in list methods,
      and how the <tt>dir()</tt> command will list them interactively,
      that seemed to most impress them.
    </p>
    <p>
      The biggest thing to repeatedly emphasize
      while showing people little impromptu Python scripts,
      I found,
      is <i>not</i> simply the clean syntax and powerful features.
      What actually surprised the experienced programmers the most,
      once I remembered to point it out to them,
      was that with Python —
      as famously Eric Raymond famously observed —
      you can write working code nearly as fast as you can type.
      Their eyes would grow wider as I made change after change
      to my script,
      without so much as an error ever appearing on the screen.
      Being able to display this in action
      easily justified having carried the monitor in from the parking lot
      and, later, carrying it back out through the rain.
    </p>
  </li>
  <li>
    <p><b>Bring a users-group sign-up sheet.</b></p>
    <p>
      It was about an hour into the Linux Fest
      that someone first asked
      if they could write their email address down
      and get information about our Python Atlanta Meetup.
      I was caught off guard;
      in this age of Internet connectedness
      and URLs,
      it had not even occurred to me
      that someone wound want
      to physically share personal information with me!
    </p>
    <p>
      I grabbed a yellow pad and,
      by judiciously adding “Name”, “Email”, and “Interest” headings,
      turned it into a sign-up sheet for the Python Atlanta Meetup.
      While I had not even thought about having
      a physical sign-up sheet,
      it's sitting next to me right now with <i>nineteen</i>
      names and addresses on it,
      whom I will be welcoming
      to the Python Atlanta Meetup mailing list tomorrow.
    </p>
  </li>
</ul>
<p>
  I hope these notes and thoughts help anyone else
  who winds up with a booth at some future event,
  and helps you create the warm and welcoming atmosphere
  for which we should all hope the Python community remains famous.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>GetPaid needs customizable forms</title>
      <link>http://rhodesmill.org/brandon/2009/getpaid-needs-customizable-forms/</link>
      <pubDate>Thu, 10 Sep 2009 00:25:46 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[plone]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/?p=144</guid>
      <description>GetPaid needs customizable forms</description>
      <content:encoded><![CDATA[
<div class="dropshadow alignright">
  <a href="http://www.plonegetpaid.com/">
    <img src="http://rhodesmill.org/brandon/static/2009/getpaid-logo.png"
         alt="GetPaid for Plone logo"
         width="330" height="83" />
  </a>
</div>
<p>
  I would like some advice from Zope and Plone folks
  about how to create forms
  that are not only easy for other developers to specialize,
  but which allow <i>several</i> specializations to be composed together.
  While I have used <tt>zope.formlib</tt> and <tt>z3c.form</tt> before
  for simple tasks,
  I have not yet been able to tell
  whether they support these more advanced kinds of operations.
</p>
<p>
  Some background:
  I am doing some work
  on <a href="http://www.plonegetpaid.com/">GetPaid for Plone</a>
  with the generous funding of Derek Richardson who,
  if his dreams had not carried him away from grad school
  at the end of the Spring semester,
  would have tackled this same work
  as part of the 2009 Google Summer of Code.
</p>
<p>
  The current mechanisms that GetPaid provides
  for customizing its checkout process are very primitive,
  and my task is to improve them.
  That is why I have been thinking about customizing forms.
</p>
<!--more-->
<h2>Plugging in payment processors</h2>
<p>
  When a Plone user has filled their shopping cart with goods
  and presses the “Checkout” button,
  GetPaid begins stepping them through a checkout process
  of several forms that must all be satisfied
  before, finally, the user's credit card will be charged
  and their purchase recorded.
  GetPaid's current definition of a “Payment Processor”
  requires only that it provide three functions
  <tt>authorize()</tt>, <tt>capture()</tt>, and <tt>refund()</tt>
  that talk on GetPaid's behalf to an online merchant account.
</p>
<p>
  This design works fine
  for traditional payment processors
  that are comfortable letting Plone handle the credit card information,
  but these days site owners usually want to delegate
  the dangerous task of handling card numbers
  to an “off-site” payment site.
  And these off-site payment processors turn out to be
  but one example
  of the many ways in which GetPaid expansion modules
  want to customize (or hijack?) the GetPaid checkout wizard.
  Consider the following scenarios:
</p>
<ul>
  <li>
    <div class="dropshadow alignright">
      <img src="https://checkout.google.com/buttons/checkout.gif?merchant_id=&w=160&h=43&style=trans&variant=text&loc=en_US"
           alt="Google Checkout sample button"
           width="160" height="43" />
    </div>
    Something like Google Checkout
    is comfortable taking the whole checkout process
    out of your hands;
    the “Checkout” button at the bottom of your shopping cart
    is replaced with a branded “Google Checkout” button
    that sends the user right to Google.
    Currently in Getpaid, that button can only be customized
    by providing completely new page templates for the shopping cart
    that duplicate everything already there,
    but which have a Google image on the checkout button.
  </li>
  <li>
    Services like PxPay (at least the way we use them)
    let the GetPaid checkout process
    take care of collecting the customer's address
    and shipping information,
    but then need the user redirected off of the Plone site.
    Again, entire views get replaced
    just to provide an alternate submit button.
  </li>
  <li>
    Many site owners want to allow several payment processors,
    with the user choosing which one gets used
    since the user might already have an account with Google Checkout
    or be previously registered with PayPal.
    This suggests the need for a “meta” payment processor
    which can be given a list of payment processors and,
    when the user reaches the first checkout step
    for which those payment processors differ,
    presents the user with a screen
    from which they select the processor that they like.
  </li>
  <li>
    Some sites have specialized information
    that they need to collect from users:
    they want to ask for extra address information,
    or extra shipping options for certain products,
    or need more contact information from the user
    when they are checking out.
  </li>
</ul>
<p>
  So, currently, in pretty much every one of the above situations,
  the answer to, “How do I tweak the GetPaid checkout process?”
  is, “Override the <i>entire</i> view or module
  that you need to customize,
  by providing your own copy
  that looks exactly the same as the default one,
  except for the one thing you need changed.”
</p>
<p>
  If you are curious, I have created
  <a href="http://rhodesmill.org/brandon/static/2009/getpaid-overrides.png"
   >a diagram showing which payment processors
    have to override which parts of GetPaid</a>.
</p>
<p>
  Not only does this wanton overriding
  mean that modules have to meticulously track
  the changes that GetPaid makes to the forms they are overriding,
  but it means that customizations are inherently not composable:
  you can't put two of them together.
</p>
<p>
  The problem of composability is a big one.
  Imagine that you live in Argentina
  and want to install a module that adjusts GetPaid's mailing address form
  to match the way postal addresses are formatted locally,
  but that you also want to use an off-site payment processor
  that needs to insert its custom “Checkout” button
  on the bottom of the mailing address form.
  Since the two modules will provide competing versions
  of the entire mailing address form,
  only one of them can “win”,
  and the customization that the other module wants to present
  will not be displayed.
</p>
<h2>Four crazy ideas</h2>
<p>
  How might checkout process customizations
  become operations that could be combined and composed,
  instead of each one of them being a fragile, blanket replacement
  of an entire part of GetPaid?
  Here are four ideas that I have thought through
  today as I sat with my trusty pencil and yellow pad:
</p>
<ul>
  <li>
    <b>Plug-in points.</b>
    Currently, GetPaid just has those three functions mentioned above
    (<tt>authorize()</tt>, <tt>capture()</tt>, and <tt>refund()</tt>)
    where payment processors can plug into its checkout logic.
    One way of solving the problems we are encountering
    is simply to provide a <i>lot</i> more plug-in points
    where GetPaid's default behavior can be adjusted or subverted.
    It looks like this would have to include separate views
    for every button, for the body of every major form,
    and for the transitions between forms.
    It is doable within the time I have left for this project,
    and serves as my default, conservative option
    if nothing more spectacular can happen right now.
    But it's very brittle:
    every time in the future that someone thinks of a new way
    of adjusting or tweaking GetPaid,
    they have to ask us to create a new plug-in point.
  </li>
  <li>
    <b>Request-level wrapper.</b>
    It might be possible
    (I mention this technique only for the sake of completeness,
    to spur our imaginations)
    to implement an off-site change processor
    as a wrapper around GetPaid
    that interacted at the bare level of incoming HTTP requests
    and outgoing HTML pages or redirections.
    If you have chosen Google Checkout,
    a special wrapper would be installed
    that would rewrite the shopping cart “Checkout” button with its own.
    If you need another field added to the final checkout page,
    you would create a wrapper that adds the field
    when it sees the HTML for that form going out,
    and that intercepts the additional field on its way back in.
    Such wrappers would at least be composable:
    you could have several active at once,
    that each made their own modification to a single page
    so that the user could see an address form
    that was formatted for Argentina
    <i>and</i> that had the correct checkout button on the bottom.
  </li>
  <li>
    <b>Wrap a form that provided an API.</b>
    What do forms “look like” to the code that calls them?
    If we imagine a form library
    where a <tt>Form</tt> is separate
    from the <tt>FormRenderer</tt>
    that introspects and traverses the properties of each form
    to turn it into HTML,
    then each GetPaid extension
    could be a wrapper around the GetPaid form object(s)
    that passes through most requests intact,
    leaving most parts of most forms alone,
    but that intercepts certain requests
    and returns different answers than GetPaid would return.
    The Argentina module would wrap the default GetPaid shipping form
    and, when traversed for its sub-forms and fields,
    would return a series of fields specific to Argentina.
    The off-site payment processor wrapper
    would just adjust the properties of the checkout button
    before returning them.
    And, these two wrappers would be composable!
    If you wrapped them,
    in any order,
    around the default GetPaid checkout forms,
    then you could enjoy both customizations.
  </li>
  <li>
    <b>Forms as modifiable objects.</b>
    What if forms — or even a small collection of forms,
    like the GetPaid checkout process — were objects
    that you could adjust and edit and modify
    before asking them to be rendered?
    Then, each GetPaid customization could be written
    as a small routine that takes, as its argument,
    a description of the <i>entire</i> checkout process,
    and that modifies that description by tweaking, adding,
    and removing everything that it needs to.
    Before rendering a view for the user,
    GetPaid would construct a copy of the checkout process,
    and then pass it, in turn, to each module.
    The Argentina module would reach in and tweak some address fields.
    The off-site processor would reach in and adjust the checkout
    button sitting below them.
    And the result could then be rendered.
    The one problem, when we compare this approach
    to the previous scenario,
    would be how to intercept new data that would be coming in
    as a result of added form fields.
    I suppose the form descriptions
    would have to include callback functions
    for processing them,
    and that extension modules would just add their own callbacks.
  </li>
</ul>
<p>
  Is there anything here worth trying?
</p>
<p>
  These are just the ideas that have come to me today,
  as I've scribbled and sketched
  and sat down to re-read all of the design patterns
  in <a href="http://www.amazon.com/gp/product/0201633612?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0201633612">the Gang of Four Book</a><img src="http://www.assoc-amazon.com/e/ir?t=letsdisthemat-20&l=as2&o=1&a=0201633612" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
  looking for inspiration.
  (You might recognize the third option above
  as something like the “decorator” design pattern!)
  Does <tt>zope.formlib</tt> or <tt>z3c.form</tt>
  or anything else like that in the Zope universe
  provide the kind of services I would need from a form library
  to implement the ideas outlined above?
</p>
<p>
  If you're a Zope or Plone person with an inkling of an answer,
  then please let me know!
</p>]]></content:encoded>
    </item>
  </channel>
</rss>

