Skip to content

Commit 7a3a67a

Browse files
authored
feat: Restructure AIPs 213 and 215, with more common proto details (#1117)
1 parent 37ec645 commit 7a3a67a

2 files changed

Lines changed: 132 additions & 102 deletions

File tree

aip/general/0213.md

Lines changed: 84 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,75 @@ placement:
99

1010
# Common components
1111

12-
In general, API reviewers encourage API producers to keep their APIs mostly
13-
self-contained, except for a relatively small set of common protos which are
14-
safe to import (e.g. [`google.protobuf.Timestamp`][timestamp]). This is for
15-
good reason: APIs generally need to be able to move forward independently of
16-
one another, and mutual dependencies can cause downstream APIs to be forced
17-
into taking major version changes or even lead to dependency conflicts.
12+
As specified in [AIP-215][], APIs must be self-contained except for the use
13+
of "common component" packages which are intended for use by multiple APIs.
1814

19-
However, there are also cases where common structures are valuable, especially
20-
where a concept is well-known and it is sufficiently clear that it will not
21-
change. Common protos serve this use case.
15+
There are two kinds of common component packages:
2216

23-
## Guidance
17+
- Organization-specific common components, covering organization-specific
18+
concepts such as a "viewport" in Maps.
19+
- Global common components which are generic (i.e. not domain-specific),
20+
such as "timestamp" or "postal address".
2421

25-
The public representation of APIs **should** be self-contained, meaning that
26-
all protos used by the API originate in the same proto `package`, except for
27-
common protos, which **may** be used freely in any API.
22+
Where it is safe to share a single representation across multiple APIs,
23+
common components can make it easier for clients to interact with those APIs.
24+
Concept-specific client code can be written once, and messages can be used from
25+
the response of one API in the request of another without clunky copying, for
26+
example.
2827

29-
APIs **must not** define a set of API-specific common protos which live outside
30-
of its versioning structure. This prevents independent movement of particular
31-
versions and also causes problems for client libraries in many languages that
32-
compile the proto messages into classes.
28+
This benefit comes with significant restrictions and limitations, however,
29+
and should not be attempted lightly.
3330

34-
APIs **should not** directly depend on protos defined in other APIs. Instead,
35-
they should copy and paste the applicable messages into their own API. When
36-
doing so, APIs **should** keep the field names and numbers the same.
31+
Note that even if the *domain* of a component is common, the requirements of
32+
a component may be organization-specific. For example, some organizations may
33+
have particular requirements of how financial values are represented, leading
34+
to multiple finance-oriented organization-specific common components - because
35+
any global common component would either not meet the organization-specific
36+
requirements, or be too complex for general use.
3737

38-
## Existing common protos
38+
## Guidance
3939

40-
The common protos, which public-facing protos for an API **may** safely import,
41-
are as follows:
40+
- Organization-wide common component packages **must** end with `.type`, e.g.
41+
`google.geo.type` or `google.shopping.type`.
42+
- Organizations **must** consult the API design team before creating a new
43+
organization-wide common component package.
44+
- Organizations **must not** define generic components in organization-specific
45+
common component packages, instead preferring global common components.
46+
- Common components **must not** be "moved" (that is, deleted from one common
47+
component package and added to a different one) from an organization-specific
48+
common component package to a global common component package or vice versa.
49+
- A common component **may** be copied from an organization-specific common
50+
component package to a global common component package (without deleting the
51+
original component) if it is found to be more widely-applicable than
52+
originally expected.
53+
- Fields **should not** be added to existing messages.
54+
- Values **should not** be added to existing enums.
55+
- Fields **must not** be removed from existing messages.
56+
- Values **must not** be removed from existing enums.
57+
- While documentation **may** be clarified, it **should not** change the
58+
meanings of existing values, including the validity of any given message
59+
or set of messages.
60+
- New proto messages and enums **may** be added to common component packages.
61+
- API teams **should** allow sufficient time for propagation to clients
62+
before using the new messages and enums in their APIs. Fields may take some
63+
time for any changes to propagate through publication to client libraries
64+
and other surfaces.
65+
- API teams **should** consult widely within their organization, and ideally
66+
with the API design team, before adding a new message or enum, due to the
67+
limitations listed above.
68+
69+
## Existing global common components
70+
71+
The global common components, which public-facing protos for an API **may** safely
72+
import, are as follows:
4273

4374
- [`google.api.*`](https://github.com/googleapis/googleapis/blob/master/google/api) (but *not* subpackages of `google.api`)
4475
- [`google.longrunning.Operation`](https://github.com/googleapis/googleapis/blob/master/google/longrunning/operations.proto)
4576
- [`google.protobuf.*`](https://github.com/protocolbuffers/protobuf/tree/master/src/google/protobuf)
4677
- [`google.rpc.*`](https://github.com/googleapis/googleapis/blob/master/google/rpc/)
4778
- [`google.type.*`][type]
4879

49-
Note that some common protos may have internal-only fields. APIs **should**
80+
Note that some common components may have internal-only fields. APIs **should**
5081
generally only rely on fields which have been
5182
[released into open source](https://github.com/googleapis/googleapis).
5283

@@ -56,9 +87,9 @@ IAM messages used throughout Google.
5687
<!-- prettier-ignore -->
5788
[iam]: https://github.com/googleapis/googleapis/tree/master/google/iam/v1
5889

59-
**Note:** Many APIs also import protos from other packages for internal-only
90+
**Note:** Many APIs also import components from other packages for internal-only
6091
use (e.g. to apply visibility labels or provide instructions to internal
61-
infrastructure). This is acceptable provided that the _public_ protos do not
92+
infrastructure). This is acceptable provided that the _public_ components do not
6293
contain such references.
6394

6495
### Protobuf types
@@ -124,31 +155,32 @@ and the definitive list is always [the code][type], several types deserve note:
124155

125156
Occasionally, it may be useful to add protos to these packages or to add to the
126157
list of commonly-available protos. In order to do this, [open an issue][] on
127-
the AIP repository in GitHub.
128-
129-
However, some general guidelines are worth noting for this:
130-
131-
- Protos **should** only be promoted to common status if we are certain that
132-
they will never change (at all -- even in ways that would normally be
133-
considered backwards compatible). Common protos are generally not versioned,
134-
and it must be the case that we can rely on the proto to be a complete and
135-
accurate representation indefinitely.
136-
- The exception to this is protos describing our infrastructure, which
137-
**may** have rare, backwards-compatible changes.
138-
- Protos must be applicable to a significant number of APIs for consideration
139-
as common protos. It is okay for those APIs to be clustered together (e.g.
140-
all in a single PA).
141-
- There is no good way to "stage" a common proto, because moving references to
142-
them is effectively not possible. (In other words, it is infeasible to add a
143-
proto to `google.geo.type.*` and then "graduate" it to `google.type.*`
144-
later.)
145-
- Adding a common proto requires coordination between several teams, and it may
146-
take time between when an addition is approved and when it is available for
147-
use.
148-
- Even after a common proto is added, APIs using local versions must continue
149-
to do so until they go to the next major version.
150-
151-
In the event that you believe adding a common proto is appropriate, please
152-
[open an issue][].
158+
the AIP repository in GitHub, noting the guidelines above.
159+
160+
## Rationale
161+
162+
Common components are effectively unversioned: APIs evolve independently of
163+
each other, both in terms of definition and implementation. A change such as
164+
adding a field is backward-compatible and predictable in specific APIs, and the
165+
API team can ensure that the server implementation is available before the API
166+
definition is published. By contrast, a change in a common component would
167+
effectively be universally available even if most API implementations did not
168+
take it into account.
169+
170+
Adding a new message or enum is backward-compatible, as it does not affect
171+
existing APIs that may import other messages or enums from the same common
172+
component package.
173+
174+
Consultation with the API design team is required for global common components
175+
and suggested for organization-specific common components as the border between
176+
"generic" and "organization-specific" is a gray area; some generic *concepts*
177+
have organization-specific use cases which surface through the components.
178+
179+
## Changelog
180+
181+
- 2023-06-XX: Restructured AIPs 215 and 213 for clarity, and introduced the
182+
concept of organization-wide common protos more formally.
183+
- 2018-08-17: Initial AIP written.
153184

154185
[open an issue]: https://github.com/googleapis/aip/issues
186+
[aip-215]: ./0215.md

aip/general/0215.md

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,59 +7,57 @@ placement:
77
order: 30
88
---
99

10-
# Common component versions
10+
# API-specific protos
1111

12-
Many APIs may support more than one version at the same time. Often, our first
13-
instinct is to create protos which are intended to be shared between API
14-
versions, and place them in an unversioned "common" directory. A similar
15-
variant to this is an _omitted_ version: a message or service that is
16-
_implicitly_ v1, but has no version in the proto package.
17-
18-
When protos are unversioned, changing them safely (that is, in a backwards
19-
compatible way) is very difficult. For example, adding a field to an
20-
unversioned proto effectively adds the field to all _existing_ versions, which
21-
do not actually support it. This is surprising to users, and creates a
22-
situation where the proto files are not accurate representations of the API
23-
surface.
24-
25-
Additionally, client library generators usually generate a class for each
26-
message in your protos in a language-appropriate namespace. In several
27-
languages, each version of your API is shipped as a _separate_ client library,
28-
and the code generator needs to generate the common messages for your API in
29-
order to ensure a complete package. This makes it difficult to use multiple
30-
APIs with similar dependent messages together.
31-
32-
For omitted versions, the version is effectively hidden, and it becomes more
33-
difficult to reason about release phases (alpha, beta, GA), with no substantive
34-
benefit.
12+
APIs are mostly defined in terms of protos which are API-specific, with
13+
occasional dependencies on common components. Keeping APIs isolated from each
14+
other avoids versioning problems and client library packaging problems.
3515

3616
## Guidance
3717

38-
- All protos specific to an API **should** be within the versioned package
39-
(e.g., `yourapi.v1.SharedProtoMessage`).
40-
41-
- In scenarios where an API doesn't consider itself to have a version, the API
42-
**must** use `v1`. (Omitted-version protos are prohibited.)
43-
44-
- When a shared proto is identical, that proto **should** be duplicated to the
45-
other versioned package (e.g., copied and pasted into
46-
`yourapi.v2.SharedProtoMessage`).
47-
48-
### What if a proto will never change?
49-
50-
There are some situations where it is useful to have an unversioned
51-
proto. These should generally apply to a complete organization or suite
52-
of APIs, not just a single API. In these situations, it may be possible
53-
to add it to our collections of common protos. Common protos are able to
54-
be used by many APIs, and are always unversioned.
55-
56-
Common protos shall always have a package structure ending in `type` (e.g.
57-
`google.type` or `google.cloud.type`).
58-
59-
**Warning:** This is a relatively rare occurrence. If you find yourself
60-
adding protos to your organizations's `type` directory frequently,
61-
double-check that this is actually where they belong.
62-
63-
For more information on common protos, consult [AIP-213][].
18+
- All protos specific to an API **must** be within a package with a major version
19+
(e.g., `google.library.v1`).
20+
- References to resources in other APIs **must** be expressed in terms of
21+
resource names ([AIP-122][]), rather than using the resource messages.
22+
- When two versions of an API use effectively the same (API-specific) proto
23+
that proto **must** be duplicated in each version. (In other words, APIs
24+
**must not** create their own "API-specific common component" packages.)
25+
- Organization-specific common components **may** be placed in a common package,
26+
as described in [AIP-213][], but **must not** be used by any API outside
27+
that organization.
28+
- Global common components (also described in AIP-213) **may** be freely used by any API.
29+
30+
## Rationale
31+
32+
When one API depends on protos defined by another API, this introduces uncertainty
33+
in terms of customer-expected behavior and client library dependency management.
34+
Suppose `google.cloud.library.v1` depends on the protos (rather than abstract resources)
35+
in `google.cloud.movies.v2`. Any change to `google.cloud.movies.v2` can cause problems.
36+
37+
For example:
38+
39+
- If a field is added to a message in `google.cloud.movies.v2`, should customers using
40+
`google.cloud.library.v1` expect to see it? If so, how soon after the field has
41+
been added? What about other API changes?
42+
- If the whole major version `google.cloud.movies.v2` is deprecated
43+
(typically after v3 has been released), does that mean `google.cloud.library.v1` has
44+
to change to use `google.cloud.movies.v3`, and if so, does that require a new major version
45+
for the library API as well?
46+
- How should client library versioning reflect changes to dependent APIs?
47+
48+
Keeping APIs isolated from each other, with a limited set of common components which are
49+
maintained in a highly disciplined way, reduces a lot of the issues with dependencies.
50+
51+
API-specific common components shared across versions add complexity for client
52+
library generation and packaging, and are inflexible in terms of versioning.
53+
When protos are duplicated because they *start* off the same in multiple versions,
54+
they can still diverge over time as they are isolated from each other.
55+
56+
## Changelog
57+
58+
2023-06-XX: Restructured AIPs 215 and 213 for clarity.
59+
2023-05-11: Changed "PA" to "organization".
60+
2018-10-01: Initial AIP written.
6461

6562
[aip-213]: ./0213.md
63+
[aip-122]: ./0122.md

0 commit comments

Comments
 (0)