OAI / Arazzo-Specification

The Arazzo Specification - A Tapestry for Deterministic API Workflows
https://spec.openapis.org/arazzo/latest.html
Apache License 2.0
221 stars 44 forks source link

3 ways to reference reusable components #181

Closed RomanHotsiy closed 6 months ago

RomanHotsiy commented 7 months ago

After reviewing the last draft of the spec I noticed there are 3 different ways to reference reusable components:

A simple object to allow referencing of objects contained within the Components Object from locations within steps or workflows in the Workflows Description. This excludes parameters and inputs defined in the components/parameters. Note - parameters should be referenced using the Reusable Parameter Object and inputs should use standard JSON Schema referencing using the $ref keyword.

We believe that the end users (authors) will be constantly confused about which to use in which context.

What problem do we solve with those 3 ways of referencing and why we can't use $refs for all of those (which users are familiar with as well as tooling support).

I believe it has to do with $ref semantics in context of JSON schema. I believe while it may improve the experience for tooling authors it makes it much worse for the end users.

But I'm not even sure if it makes it easier for the tooling authors as now we have to deal with more error messages and validations.


On a separate note I'm not clear why the Reusable objects has this specific structure:

{
    "name": "{$components.successActions.notify}"
}

The moment that I'm unclear about is why the field is called name while the expression does not resolve to the name or anything like name?

frankkilcommins commented 7 months ago

@RomanHotsiy the 3 options have been grating a little with me too. I'm already thinking of consolidating Reusable Parameter Object into Reusable Object and only allow value overrides where the referenced object is a Parameter Object.

I can bite the bullet and rename name to reference too as part of the same effort. This was a mediocre attempt to stay even further away from a clash, but I now think that clear explaining how you reference a JSON Schema object versus a non JSON Schema object is clearer (also helped by just having two mechanisms rather than 3)

Removing the keyword clash with JSON Schema's $ref is indeed the primary motivation. There's a whole world of pain caused by this as well as real inabilities to adequately resolve references based on lack of clarity on how to deal with different JSON Schema versions in referenced fragments as well as dealing with the direction of resolution and upgrading or downgrading accordingly. It's completely left up to an implementor to decide which results in interoperability issues.

The same mantra of moving away from the current OAS Reference Object (which contains the keyword clash) is also being proposed for the next version of OAS.

frankkilcommins commented 7 months ago

@RomanHotsiy - hopefully #182 simplifies the situation

RomanHotsiy commented 6 months ago

@frankkilcommins this makes it better for sure! Thanks.

Yet I'm still confused why we have to invent a new way of reuse just for this spec. Whatever reusability mechanism is planned for Moonwalk it seems to be different form this.

So instead of a single reusability mechanism ($ref) we're inventing new ones for each spec.

I understand this is part of a broader discussion about $ref's semantics.

handrews commented 6 months ago

@RomanHotsiy the Moonwalk discussion isn't settled yet, and I'm paying attention to how this works out as we try to figure that out.

So instead of a single reusability mechanism ($ref) we're inventing new ones for each spec.

Because we don't have a single re-usability mechanism. We have at least 9 across 3.0 and 3.1 (6 in 3.0, 8 in 3.1, 5 overlapping):

There are also numerous features that have implicit correlations - path or server template variables names, jsonSchemaDialect setting the default $schema, and probably other things I'm forgetting (the OASComply reports directory should have the complete taxonomy).

EDIT: And the way Server Objects get looked up across Operation, Path Item, and the root Object, which, like the component name connections, becomes ambiguous if you reference a complete document that has its own Components Object and/or root-level Servers Object).

LATER EDIT: Oh and the way tags can optionally connect to Tag Objects

handrews commented 6 months ago

This is not even getting into the fact that some of those linkages that use URI-references resolve as URLs (strictly location-based) and some in 3.1 resolve as URIs (identifiers that need not correlate to location).

handrews commented 6 months ago

Plus, tooling support for $ref in any form is egregiously inconsistent, and often outright incorrect. Too many tools refuse to process it, or refuse all but a few uses, or require its removal by a preprocessor. It's not like it's a system with good interoperability and consistent support. Nor does $ref meet the intuitive expectations of the many users who expect it to do some sort of merge, which none of the variations do.

$ref, with it's variable behavior and inconsistent support, is a huge pain point for consulting clients of mine that are trying to implement large-scale re-use across multiple providers. It's just not sufficiently interoperable or reliable, and the variations are too hard to understand. Workflows is specifically intended to span multiple API providers, and is likely to run into these problems. Without doing this, it was going to introduce at least one more $ref variation to that poorly-supported tangle of variations. Having recently implemented all forms of referencing (by URI-reference or component name or operationId) in both 3.0 and 3.1, throwing more complexity onto that fire really does not feel like a win to me.