plone.api first impressions

Seems like Plone is getting an API that strives to keep your mental sanity

For quite some time, Plone has been widely regarded as "complex", and not very friendly for "incoming developers", i.e. those unfortunate souls that, for the very first time in their lives, embarked on the exciting adventure known as "developing a Plone site with some customizations"[1].

However, while some good old fashioned danger is exciting and keeps your adrenaline levels high, it does have downsides, and for this exact reason at the Plone Konferenz in Münich, some developers gathered up and sketched out a small but powerful package called plone.api.

The purpose of the package is to provide "an elegant and simple API, built for humans wishing to develop with Plone".

This effort will, in my opinion, help making Plone a much nicer system to develop for, and reduce casualties among those that approach Plone for the very first time. It might make some seasoned, adrenaline-addicted Plone developers a little bit bored, but it's a price worth paying.

Therefore, upon learning that the preliminary documentation was online, I went to see it immediately (both because I was interested, and because I tend to click compulsively on any link).

And I was very pleased about what I saw, the documentation was very readable and the API looked clean and intuitive.



There is one thing in the documentation I strongly disagree with, and I'll try to explain here why. The "offending" part is the following:

No positional arguments. Only named (keyword) arguments.

  1. There will never be a doubt when writing a method on whether an argument should be positional or not. Decision already made.
  2. There will never be a doubt when using the API on which argument comes first, and which ones are named. All arguments are named.
  3. When using positional arguments, the method signature is dictated by the underlying implementation. Think required vs. optional arguments. Named arguments are always optional in Python. This allows us to change implementation details and leave the signature unchanged.
  4. The arguments can all be passed as a dictionary.

Which means that instead of having:

def pick_and_store(what, where):
    print "You picked %s and stored it in %s" % (what, where)

you will have:

def pick_and_store(what, where):
    if len(args) > 0:
        raise TypeError("No args allowed")
    if what is None or where is None:
        raise TypeError("I need to know what you want to pick and where you want to put it")
    print "You picked %s and stored it in %s" % (what, where)

Besides the fact that this choice forces some boilerplate to be repeated with every function (but this can be mitigated with decorators) I don't see the need for it at all.

Let's see the point the plone.api documentation makes in favour of this decision (one by one) and I'll try to explain my point of view.

There will never be a doubt when writing a method on whether an argument should be positional or not

Let's start with the fact that, in Python, is up to the calling to decide if to use positional arguments or not, and this can't be forced by the called function.

>>> def foo(one, two):
...     print one, two
>>> foo(**{ 'one': 1, 'two': 2 })
1 2
>>> foo(two=2, one=1)
1 2
>>> foo(1, 2)
1 2
>>> foo(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 2 arguments (1 given)
>>> def foo(one=None, two=None):
...     print 1, 2
>>> foo(1, 2)
1 2

Which means that yes, I strongly advocate calling any API using named arguments instead of relying on the position of them remaining unchanged, and I abhor functions whose signatures with *args and **kwargs (unless they are unavoidable®).

Actually, in Python, every function can be called using the positional notation or the named argument notation, independently of the function signatures. The syntax argument=value is merely there to provide optional parameters. So the decision is quite simple, and there is no ambiguity about it. The caller then can be advised against using positional notation to call functions (maybe with a giant "don't assume we'll never change the order of the arguments" warning), but this cannot be enforced.

There will never be a doubt when using the API on which argument comes first, and which ones are named

You can already name all arguments, or none, and there's nothing your function can do about it. Plus, sometimes, certain names are hard to write (for me, at least). For example, 50% of the time I try to write "fixture" I end up with "ficture". Or the name might be hard to remember (again, the constructor of datetime.time: does it take hours= or hour=?). I think it's only switching the problem.

The arguments can all be passed as a dictionary

Well, again, this is possible whatever you do, except if the function has a signature like this: foo(*args). Which is agreed we should avoid.

This allows us to change implementation details and leave the signature unchanged

This is not true. Even if you don't use the current plone.api approach, if you have a previously non-optional argument that becomes optional, no pre-existing code will break. On the contrary, if you have a previously optional argument that becomes mandatory, things will break and, as a further problem, it won't be all that obvious from the traceback (it is however quite obvious from the signature if you use the "traditional" approach)

So, what do you propose?

First of all, advising users that they should not rely on the order of the arguments being unchanged. The, avoiding at all costs *args and **kwargs in the function signatures and, lastly, using default values for arguments only for the arguments that are really optional. With these small changes, I think plone.api will be much better.


In the end, I applaud the effort of those that worked hard on drafting plone.api, and I hope they will correct what I see as an unnecessary "wart" on an otherwise clean, concise, pythonic API.

    [1] There are unconfirmed rumours that George Lucas has heard about this, and that the next Indiana Jones movie will be titled "Indiana Jones and the secrets of the ZCA"

    Share this on

    Share |

    On same topics


    comments powered by Disqus