Re: An updated draft of the schema.org/Action proposal

On Wed, Nov 27, 2013 at 6:37 AM, Markus Lanthaler
<markus.lanthaler@gmx.net>wrote:

> On Tuesday, November 26, 2013 7:39 PM, Sam Goto wrote:
> > On Wed, Nov 20, 2013 at 8:40 AM, Markus Lanthaler wrote:
> > > Hmm... you changed "expects" to take a SupportedProperty instead of a
> > > Class which results in a asymmetry with "returns" which still takes a
> > > Class.
> >
> > Right. That maps more closely to the API that gmail launched with and it
> > also maps better to the use cases we have with indexing <forms>.
>
> Right, but adding another object in between even if it has nothing else
> than
> a supportedProperties member wouldn't hurt much IMO. It would also open the
> door to, e.g., support binary data.
>
>
> > But most importantly, this doesn't corner us to taking Class in case we
> > need to in the future.
>
> But it makes it more difficult and introduces a mismatch between Schema.org
> and Hydra which I would like to avoid.
>
>
> > > Furthermore, SupportedProperty has no "property" property anymore but
> > > you use "name" to specify it - which is a string and could be anything.
> >
> > SupportedProperty extends from Property, so it doesn't need to take one.
>
> This doesn't make any sense to me as it makes it completely impossible to
> reuse any of the existing Schema.org properties (or any property in another
> vocabulary for that matter).
>

Got it. So instead of referring to the property via the "name" (e.g.
"description"), you use URI identifiers instead (e.g.
http://schema.org/description), which buys you precision in exchange for
verbosity?


>
>
> > > > In most cases a human-readable label to be read in a dynamically
> > > > generated UI or documentation.
> > >
> > > I'm not sure I like this design. The reason is that most developers
> > > think in terms of (resource) classes. This is pretty apparent even if
> > > you just look at three arbitrary Web APIs:
> > >
> > > Google+: https://developers.google.com/+/api/latest/
> >
> > I am/was actively involved in most of these APIs :)
>
> Then your change surprises me even more as the documentation uses exactly
> the structure I'm proposing. For example (citing [1]):
>

You are right. I think that thinking in terms of resources (rather than
RPCs) gets lots of things simplified. Specifically, the following:

- collections: which allows you to do things like (a) searching for
resources and (b) creating/acting on resources even before they exist
- resource hopping: moving from one resource to another and performing
operations in the right context
- dynamic operations: as resource state changes, operations available in
them are now made possible to change

Here are a few demos I'm writing to validate this model with a few real
world use cases that are relevant:

http://code.sgo.to/crawler/yaap.html#url=http://code.sgo.to


>
>    Moments: insert
>    ===============
>
>    ## Request body ##
>
>    In the request body, supply a **Moments resource** with the following
>    properties:
>
>    Property name | Value          | Description            | Notes
>    --------------------------------------------------------------------
>    Required Properties
>    --------------------------------------------------------------------
>    target        | nested object  | The object on which... |
>    type          | string         | The Google schema....  | writable
>    --------------------------------------------------------------------
>    Optional Properties
>    --------------------------------------------------------------------
>    startDate     | datetime       | Time stamp of when...  | writable
>
>
>    ## Response ##
>
>    If successful, this method returns a **Moments resource** in the
>    response body.
>
> Could be translated directly into (omitting range information):
>
>   {
>     "name": "Moments: insert",
>     "@type": "Operation",
>     "method": "POST",
>     "expects": {
>       "@id": "#Moments",
>       "supportedProperties": [
>         {
>           "@id": "#target",
>           "name": "The object on which...",
>           "required": true
>         },
>         {
>           "@id": "#type",
>           "name": "The Google schema...",
>           "required": true
>         }
>         {
>           "@id": "#startDate",
>           "name": "Time stamp of when...",
>           "required": false
>         }
>       ]
>     },
>     "returns": "#Moments"
>   }
>
>
> > > I think it's important to have something that mimics that. That's why I
> > > introduced the supportedProperties property in the first place. If
> > > there's no existing class which specifies the supportedProperties you
> > > need, you subclass one (or more) and specify them yourself. Then you
> > > can easily reuse that new class consistently across your API.
> >
> > That's certainly a possibility. Most of our existing users (e.g. gmail
> > actions, g+ actions, yandex islands) take the entire action as the
> > payload/request/parameters, rather than an individual noun/class.
>
> And nothing would stop them doing so in the future.. regardless of
> "expects"
> takes a class or not.
>
>
> > I certainly agree that we could eventually find that we'd need to pass
> > just nouns/classes, but at the moment we've been fairly happy with the
> > transfer of the entire action between parties.
>
> I'm not proposing to change that -- even though I think it might make a lot
> of sense for products such as Actions in GMail which will just accept
> certain classes/properties anyway.
>
>
> > Most importantly, with "expects" and "returns" being schema.orgproperties
> > they can evolve incrementally over time to take other types (e.g. Class),
> > so hopefully we can cross this bridge when we get to it.
>
> I really don't understand the reasons for the deviation of the model Hydra
> or (Resource Shapes) follow. Are you concerned about the complexity? I
> think
> it makes things much easier to understand a allows reuse which is
> impossible
> if a just a set of SupportedProperties is used.
>
> Have you had the chance to take a look at [2]? Would love to hear your
> opinions?
>

I did, yes, thank you that's super helpful.

I think SupportedClasses make sense, but I'm still unhappy with complexity
and verbosity of large API specifications when you get into the "nested
requirements case" (which gmail is addressing via a "path-like" syntax with
things like "review.reviewBody" to refer to the "reviewBody" property
inside "review") ... Take food orders as an example:

http://code.sgo.to/crawler/yaap.html#url=http://code.sgo.to/restaurants/123/orders

It ends up with a quite large/verbose/complex set of requirements and
expectations, and I'm trying to find ways to compress that into something
cleaner for the simple case.

Here is another example that I explored a bit deeper:

http://code.sgo.to/crawler/yaap.html#url=http://code.sgo.to/hotels/123

One idea is to take advantage of the fact that most times you want to
express whether a property is required or not (rather things like
cardinality, min/max values, etc). For example, if we (a) break down
http://schema.org/SupportedClass.supportedProperty-ies into
requiredProperty and optionalProperty and (b) let it take
http://schema.org/Property (in addition to
http://schema.org/SupportedProperty, which no longer holds whether the
property is required or not), it avoids having to instantiate a new
SupportedProperty.

In the complex case (e.g. requirements on cardinality, min/max values,
enumerations, etc), requiredProperty and optionalProperty may still take a
SupportedProperty in case it needs to be more specific.

Here is what this
http://code.sgo.to/crawler/yaap.html#url=http://code.sgo.to/hotels/123would
look like with these constructs:

{
  "@context": "http://schema.org",
  "@type": "Hotel",
  "@id": "http://localhost:5000/hotels/123",
  "name": "Hilton",
  "reservations": {
    "@type": "ItemList",
    "@id": "http://localhost:5000/hotels/123/reservations",
    "operation": {
      "@type": "SearchAction",
      "actionStatus": "proposed",
      "expects": [{
          "@type": "SupportedClass",
          "subClassOf": "LodgingReservation",
          "requiredProperty": [
             "http://schema.org/checkInDate",
             "http://schema.org/checkOutDate",
             "http://schema.org/numberOfAdults",
             "http://schema.org/numberOfChildren"
          ]
      }],
      "returns": "http://schema.org/ItemList",
      "actionHandler": [
        {
          "@type": "HttpHandler",
          "name": "Creates a new reservation for this hotel",
          "httpMethod": "post",
        }
      ]
    }
  }
}



>
> Thanks,
> Markus
>
>
> [1] https://developers.google.com/+/api/latest/moments/insert
> [2] http://www.hydra-cg.com/spec/latest/schema.org/
>
>
> --
> Markus Lanthaler
> @markuslanthaler
>
>
>

Received on Friday, 24 January 2014 01:24:23 UTC