[Microbit-Python] Accessor API design on the micro:bit

Michael sparks.m at gmail.com
Fri Oct 30 13:19:04 EDT 2015


This discussion came up on this mailing list after the Pycon UK sprints as
well:

> Subject:   [Microbit-Python] Flat API
> Date: 22 September 2015 at 00:52

... and in it I raised the issue of properties. (I was in favour of
properties)

Summarising the thread  point was raised that you have a choice:

 1 Exposing some things as properties and some as set_{thing} and
get_{thing}
 2 Exposing everything as properties
 3 Exposing everything as set_{thing} and get_{thing}

The consensus of that discussion was that (1) would be confusing since
rather than one concept for setting/getting things you need to understand
2. In the case of a complete full range ability set in schools, this is
problematic. Every Y7 age child in the UK means *every* Y7 child, including
those who are the most challenged. (I'm not arguing fighting to build
something for lowest common denominator, just not abandoning the lowest
quartile - since that way chaos in classroom's ensues... )

That leave 2) and 3). IMO, it's simply not practical to have *everything*
as properties. The particular discussion point used that I'm referring to
related to pins, and the comment that I'm referring to here is this:

Tom Viner wrote:
> I don't actually think microbit.dpin0 = True is pythonic if that does
anything
> other than set (and completely override) a variable value. And I think we
> agreed yesterday that standard properties were an extra concept to
> explain, and furthermore not introspectable. So that rules out
> mb.dpin0 = True too.

The argument made the point that you're saying this:

    somevalue_value = some.name.somewhere
    some.name.somewhere = 5

means something different to:

    pin_value = some.name.somewhere
    some.name.somepin_as_a_property = 5

In terms of the overall effect.

In an API designed for standard usage, I wouldn't have a problem with this.
Indeed I argued (weakly) for it.

However, if instead you have this:

    pin_value = some.name.somepin.get_value()
    some.name.somepin.set_value(5)

Then you have something you can attach help to.

Given that discussion, that suggests that using properties everywhere isn't
appropriate, resulting in the choice to use option 3 - to use get_{thing}
set_{thing} everywhere.

I personally think that that argument is much stronger than the one around
lambda's. Indeed, even though the argument for lambdas also applies to list
comprehensions etc, I still think that's a weak argument.

That said, all 4 points you list in points 1 - 4 I completely agree with. I
just don't think this about callbacks.

This is more about having just one painfully literally obvious and
introspectable way to do it.

I do think however, having worked with kids, that when you create an API
for children, it really does have to be simpler than most people realise,
and get/set is a really good sign post - even though in "real" APIs you
wouldn't do that.

For example, this is going to 11/12 year olds - in the UK computing
syllabus they won't get to object orientation until 16/17 (A-Levels) -
which means some schools DO actively avoid anything that looks vaguely
object based *because* they're dealing with such a wide range of abilities.
(Again, I'm not saying we should pander to that, but knowing about it is
useful)

ie IMO it's not really a pythonic/non-pythonic decision that was taken back
in september, but one focussed on the pedagogical practicalities.

(This is a bit like the prototype's DAL was more focussed on pedagogical
practicality than the production version's DAL is - I'd always expected to
enable older children to hack on the DAL - which won't be practical now
AFAICT- but I digress.)

For reference, I'm not arguing one way or the other, but just recounting
the process that got us here, and as I say, I think the lambda argument is
a complete red herring - pretty much for the reasons you say.

</thruppenceworth>

Regards,


Michael

On 30 October 2015 at 16:11, Larry Hastings <larry at hastings.org> wrote:

>
>
> I want to revisit something that was decided during the sprints at PyCon
> UK.  On a Github PR today (
> https://github.com/bbcmicrobit/micropython/pull/58 ) there was a short
> discussion about how to spell "give me the x coordinate reading from the
> accelerometer object".  I suggested "accelerometer.x".  In response, Damien
> George said:
>
> We discussed this at length at PyCon UK: we use functions for everything.
> It's more consistent (and setters like obj.attr = 1 can't be used in a
> lambda, while obj.set_attr(1) can).
>
>
> Nick Tollervey said, nigh-simultaneously:
>
> I seem to remember having a conversation about get_foo() v foo or foo() at
> PyCon UK. IIRC we agreed to keep such things as method calls since that's a
> consistent pattern in the way the API is written. I also remember a
> discussion about using explicit verbs in the method name so kids
> immediately understood what it was they were calling. I.e. get_foo() is
> more obvious than simply just foo().
>
>
> I'm all for consistency, but in this case I think the group has chosen to
> be consistent in the wrong way. Things like "accelerometer.x" are
> *exactly* what the descriptor protocol is for. The spelling couldn't be
> clearer, not to mention it's easy to read and pleasingly short to type. I
> would absolutely 100% design my API that way for adults and I think it's
> better for kids too.
>
> It's true that you can't use an assignment statement in a lambda function.
> But:
>
>    1. one shouldn't warp one's API design to accommodate lambda functions,
>    2. accelerometer.x is read-only,
>    3. I doubt the curriculum for 11-year-olds will include lambda, and
>    4. I propose we strenuously avoid callback-based APIs. ("I don't like
>    callback interfaces, I always get them wrong" --GvR (quote is approximate))
>    Iteration > callbacks.  For example, Python's sched.Scheduler class has a
>    callback-based API, but the Scheduler class I've written for the micro:bit
>    (coming soon!) does not.
>
>
> I'd greatly rather see us make properties of objects behave like simple
> attributes, using descriptors where necessary. I suggest that's far more
> Pythonic--accessor functions always feel like Java or C++ to me.  (Indeed,
> ISTM the descriptor protocol was added to Python precisely so we don't ever
> need accessor functions!)
>
> It's our API, we can spell it any way we like.  I propose we use simple
> attributes nearly everywhere, using descriptors where necessary. I'd
> reserve the .set_x() accessor method spelling for the rare attribute that
> actively changes something (e.g. microbit.display.set_display_mode). And I
> still might use a read-only descriptor instead of a .get_x() method for
> those. (Though I'd have to think about that one, and/or play with some
> examples.)
>
>
> Cheers,
>
>
> */arry*
>
> _______________________________________________
> Microbit mailing list
> Microbit at python.org
> https://mail.python.org/mailman/listinfo/microbit
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.python.org/mailman/private/microbit/attachments/20151030/0b3fa345/attachment-0001.html>


More information about the Microbit mailing list