-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Service renames #734
Service renames #734
Conversation
This commit adds the ability to rename shapes within the context of the closure of a service. This helps to allow models that aggregate other models of disparate teams to have a recourse when shapes across namespaces conflict when they are used in the same service.
Seems reasonable. Would appreciate some sort of My one main worry is that now I wonder if that should be deprecated and a service-aware name accessor should be added? Another wrinkle: What happens if two errors with the same name (but renamed within the closure) are added to the errors for an operation? Is that verboten? |
Since there are valid use cases where a service context isn't needed, shape ID names shouldn't be deprecated (for example, Smithy to Smithy transformations and the implementation of the Smithy model itself). For making this easier, rather than adding a new knowledge index, I added a
But maybe it would be better to put that method on a
Great question. For context: errors are one of the few places where a polymorphic type needs to be communicated. For example, clients need to look at the response We could address this in a few ways:
|
[Discussed offline]
In terms of codegen, a couple of protocol tests should be sufficient to make sure that teams are properly respecting the rename flag for structures. |
* Add more discoverable methods to ShapeId to get a contextual name. * Add a protocol test to ensure generators can handle renames. * Update spec to forbid renaming errors. * Update validator to forbid error renames, and give better error messages. * Update ServiceShape#getContextName to ServiceShape#getContextualName
I've updated the proposal and the pull request with the discussed changes. Thanks for the suggestions! |
This pull request adds the ability for service shapes to use shapes that have conflicting shape names in the service closure.
Motivation
All the shapes referenced as part of a service are called the service closure. The service closure is computed by recursively following each reference to operation and resource shapes defined on the service, then to their operations and resources, and then to the shapes they reference. With some exceptions defined in the specification, Smithy requires every shape in the closure to have a unique shape name regardless of their namespaces. Given that Smithy supports defining shapes in namespaces, this limitation that shapes names must be unique was counter-intuitive, and there was previously no recourse when the situation occurs. Smithy models are often used by teams to combine the models of several independent microservices into a unified service, so it's a common occurrence that teams end up with name conflicts when building their "frontend" services.
Background
The intentional limitation that shape names must be case-insensitively unique in a service closure is intended to help with code generation to generate unambiguous type names. Borrowing from DDD terminology, the goal is to give the service a ubiquitous language by treating a service as a bounded context.
Solution
The solution proposed in this pull request is to introduce a
rename
property to the service shape to disambiguate shape name conflicts in the service closure. This property is a map of shape IDs contained in the service to the name to give the shape when used in the context of the service.rename
property does not add a new selector relationship from the service to the renamed shapes, and because of this, the rules around referencing shapes marked as private from other namespaces do not apply to a service.The following example defines a service that contains two shapes named "Widget" in its closure. This model is invalid because on the conflicting names:
The conflicting
Widget
shapes can be disambiguated by renaming one of the "Widget" shapes used in the service:Impact on code generation
Code generators should now take into account the
rename
property of a service to determine the name of a shape for the target language. Code generators previously based the name of a generated type solely on the name of a shape's shape ID, but the now must now have the context of the service being generated to choose an appropriate type name for shapes, particularly conflicting shapes.Impact on OpenAPI conversion
Like code generators, when generating OpenAPI models from Smithy, the converter must now use the
rename
property of the service.Impact on non-Smithy AWS SDKs
Several AWS SDKs have not yet migrated to Smithy models and code generation. These SDKs will not need to do any work in order for this proposal to work. The conversions from Smithy to the format used by these SDKs will automatically rename shapes as part of the generated model.
Alternatives considered
Do nothing, copy and paste
If a conflict occurs when integrating models, the shapes that are in conflict can be copied and renamed to names that no longer conflict with the rest of the model. This solution is simple in implementation and the specification, but it's an awful experience for the team that has this problem. Sometimes renaming a shape requires renaming and editing an entire tree of interconnected shapes; any member that targeted the previous shape name needs to be updated, traits need to be updated, etc. This solution is also dangerous too; the copied shapes are now disjoint from their source. As the source model evolves, the copied shapes only evolve if another explicit copy is performed, or if some kind of automated copy is performed. However, there is still an opportunity for the copied shapes to become out of sync because traits can be applied to the copied shapes that have no impact on the source shapes.
Relax the unique name requirement and use build tooling
Another option is to relax the requirement that shape names are unique across namespaces and rely on codegen configuration in
smithy-build.json
files to disambiguate shape names. For example:The biggest issue with this approach is that it doesn’t scale well if a service needs to be generated in multiple programming languages and potentially by multiple teams (for example, that is the situation with AWS SDKs). By putting rename metadata in the model, the team that owns the service has full control over how the shapes in their service are referenced in things like code and documentation. Placing this configuration in build configuration files pushes the burden onto consumers and can easily lead to inconsistencies.
Use a
rename
traitThis option is similar to the option proposed, but instead of making
rename
a property of the service, it becomes a trait on the service:This has the same effect, and really comes down to a matter of taste. Because the concept of a "service closure" is specific to a service and defined by properties within the service like
operations
andresources
, it seems more natural to define renames inside the service as well.Add a new
context
shapeA new shape could be added called
context
that is referenced by a service to handle renames.This has the benefit that contexts could be reused by multiple services, and could even be used to generate just types for shapes rather than clients or servers.
smithy-build.json
files could reference the service to generate a client or server, or the context to generate shapes in a context:This option has several issues: